Skip to content

Commit 970ca12

Browse files
authored
Merge pull request #761 from dev-protocol/improve/positionsCreate
upgrade: positionsCreate API
2 parents a8e8bab + bee1f7b commit 970ca12

48 files changed

Lines changed: 230 additions & 27 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/* eslint-disable functional/functional-parameters */
2+
import { whenDefinedAll } from '@devprotocol/util-ts'
3+
import {
4+
TransactionResponse,
5+
TransactionReceipt,
6+
} from '@ethersproject/abstract-provider'
7+
import { Provider } from '@ethersproject/abstract-provider'
8+
import { BigNumber } from 'ethers'
9+
import { FallbackableOverrides } from '../../common/utils/execute'
10+
import { devClients } from './clients/devClients'
11+
12+
type ApproveIfNeeded = (factoryOptions: {
13+
readonly provider: Provider
14+
readonly requiredAmount: string
15+
readonly from: string
16+
readonly to?: string
17+
readonly callback: (
18+
receipt?: TransactionReceipt
19+
) => Promise<TransactionResponse>
20+
}) => (options: {
21+
readonly amount?: string
22+
readonly overrides?: FallbackableOverrides
23+
}) => Promise<{
24+
readonly waitOrSkip: () => Promise<TransactionResponse>
25+
}>
26+
27+
export const approveIfNeeded: ApproveIfNeeded =
28+
(factoryOptions) => async (options) => {
29+
const [l1, l2] = await devClients(factoryOptions.provider)
30+
const client = l1 ?? l2
31+
const allowance = await whenDefinedAll(
32+
[client, factoryOptions.to],
33+
([x, to]) => x.allowance(factoryOptions.from, to)
34+
)
35+
const callback = {
36+
waitOrSkip: () => factoryOptions.callback(),
37+
} as const
38+
39+
return (
40+
whenDefinedAll([client, factoryOptions.to], async ([dev, to]) => {
41+
return BigNumber.from(allowance).lt(factoryOptions.requiredAmount)
42+
? ((approve) =>
43+
({
44+
...approve,
45+
waitOrSkip: async () => {
46+
const repeipt = await approve.wait()
47+
return factoryOptions.callback(repeipt)
48+
},
49+
} as const))(
50+
await dev.approve(
51+
to,
52+
options.amount ?? factoryOptions.requiredAmount,
53+
options.overrides
54+
)
55+
)
56+
: callback
57+
}) ?? callback
58+
)
59+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { l2AvailableNetworks } from '../const'
2+
import type { UndefinedOr } from '@devprotocol/util-ts'
3+
import { createDevContract, DevContract } from '../../../ethereum/dev'
4+
import {
5+
createDevContract as createDevContractL2,
6+
DevContract as DevContractL2,
7+
} from '../../../l2/dev'
8+
import { Provider } from '@ethersproject/abstract-provider'
9+
import { registryClientL1 } from './registryClientL1'
10+
11+
type Results = readonly [UndefinedOr<DevContract>, UndefinedOr<DevContractL2>]
12+
13+
const cache: WeakMap<Provider, Results> = new WeakMap()
14+
15+
export const devClients = async (provider: Provider): Promise<Results> => {
16+
const res =
17+
cache.get(provider) ??
18+
(await (async () => {
19+
const net = await provider.getNetwork()
20+
const registry = await registryClientL1(provider)
21+
const l1 = registry
22+
? createDevContract(provider)(await registry.token())
23+
: undefined
24+
const l2 = ((data) =>
25+
data ? createDevContractL2(provider)(data.map.token) : undefined)(
26+
l2AvailableNetworks.find(({ chainId }) => chainId === net.chainId)
27+
)
28+
const results: Results = [l1, l2]
29+
// eslint-disable-next-line functional/no-expression-statement
30+
cache.set(provider, results)
31+
return results
32+
})())
33+
return res
34+
}

lib/agent/common/clients/lockupClients.ts

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,14 @@ import {
88
import { Provider } from '@ethersproject/abstract-provider'
99
import { registryClientL1 } from './registryClientL1'
1010

11-
const cache: WeakMap<
12-
Provider,
13-
readonly [UndefinedOr<LockupContract>, UndefinedOr<LockupContractL2>]
14-
> = new WeakMap()
11+
type Results = readonly [
12+
UndefinedOr<LockupContract>,
13+
UndefinedOr<LockupContractL2>
14+
]
1515

16-
export const lockupClients = async (
17-
provider: Provider
18-
): Promise<
19-
readonly [UndefinedOr<LockupContract>, UndefinedOr<LockupContractL2>]
20-
> => {
16+
const cache: WeakMap<Provider, Results> = new WeakMap()
17+
18+
export const lockupClients = async (provider: Provider): Promise<Results> => {
2119
const res =
2220
cache.get(provider) ??
2321
(await (async () => {
@@ -30,10 +28,7 @@ export const lockupClients = async (
3028
data ? createLockupContractL2(provider)(data.map.lockup) : undefined)(
3129
l2AvailableNetworks.find(({ chainId }) => chainId === net.chainId)
3230
)
33-
const results: readonly [
34-
UndefinedOr<LockupContract>,
35-
UndefinedOr<LockupContractL2>
36-
] = [l1, l2]
31+
const results: Results = [l1, l2]
3732
// eslint-disable-next-line functional/no-expression-statement
3833
cache.set(provider, results)
3934
return results

lib/agent/positionsCreate.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,46 @@
1-
import { TransactionResponse } from '@ethersproject/abstract-provider'
21
import { FallbackableOverrides } from '../common/utils/execute'
32
import { Provider } from '@ethersproject/abstract-provider'
4-
import { UndefinedOr } from '@devprotocol/util-ts'
53
import { lockupClients } from './common/clients/lockupClients'
4+
import { approveIfNeeded as _approveIfNeeded } from './common/approveIfNeeded'
5+
import { UndefinedOr } from '@devprotocol/util-ts'
66

77
type PositionsCreate = (options: {
88
readonly provider: Provider
9+
readonly from: string
910
readonly destination: string
1011
readonly amount: string
1112
readonly overrides?: FallbackableOverrides
12-
}) => Promise<UndefinedOr<TransactionResponse>>
13+
}) => Promise<
14+
UndefinedOr<{
15+
readonly approveIfNeeded: ReturnType<typeof _approveIfNeeded>
16+
}>
17+
>
1318

1419
export const positionsCreate: PositionsCreate = async (options) => {
1520
const [l1, l2] = await lockupClients(options.provider)
1621

17-
return l1
18-
? l1.depositToProperty(options.destination, options.amount)
19-
: l2
20-
? l2.depositToProperty(options.destination, options.amount)
22+
return l1 || l2
23+
? {
24+
approveIfNeeded: _approveIfNeeded({
25+
provider: options.provider,
26+
requiredAmount: options.amount,
27+
from: options.from,
28+
to: ((x) => x?.contract().address)(l1 ?? l2),
29+
callback: (receipt) =>
30+
l1
31+
? l1.depositToProperty(
32+
options.destination,
33+
options.amount,
34+
options.overrides
35+
)
36+
: l2
37+
? l2.depositToProperty(
38+
options.destination,
39+
options.amount,
40+
options.overrides
41+
)
42+
: (undefined as never),
43+
}),
44+
}
2145
: undefined
2246
}

lib/ethereum/allocator/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ describe('allocator/index.ts', () => {
2525
return {
2626
calculateMaxRewardsPerBlock:
2727
createCalculateMaxRewardsPerBlockCaller(contract),
28+
contract: () => contract,
2829
}
2930
}
3031

lib/ethereum/allocator/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { Provider } from '@ethersproject/abstract-provider'
33
import { Signer } from '@ethersproject/abstract-signer'
44
import { allocatorAbi } from './abi'
55
import { createCalculateMaxRewardsPerBlockCaller } from './calculateMaxRewardsPerBlock'
6+
import { always } from 'ramda'
67

78
export type CreateAllocatorContract = {
89
readonly calculateMaxRewardsPerBlock: () => Promise<string>
10+
readonly contract: () => ethers.Contract
911
}
1012

1113
export const createAllocatorContract =
@@ -15,5 +17,6 @@ export const createAllocatorContract =
1517
return {
1618
calculateMaxRewardsPerBlock:
1719
createCalculateMaxRewardsPerBlockCaller(contract),
20+
contract: always(contract),
1821
}
1922
}

lib/ethereum/dev/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { createAllowanceCaller } from '../../common/erc20/allowance'
1414
import { createDepositCaller } from './deposit'
1515
import { FallbackableOverrides } from '../../common/utils/execute'
1616
import { TransactionResponse } from '@ethersproject/abstract-provider'
17+
import { always } from 'ramda'
1718

1819
export type DevContract = {
1920
readonly totalSupply: () => Promise<string>
@@ -34,6 +35,7 @@ export type DevContract = {
3435
value: string,
3536
overrides?: FallbackableOverrides
3637
) => Promise<TransactionResponse>
38+
readonly contract: () => ethers.Contract
3739
}
3840

3941
export const createDevContract =
@@ -52,5 +54,6 @@ export const createDevContract =
5254
symbol: createSymbolCaller(contract),
5355
decimals: createDecimalsCaller(contract),
5456
deposit: createDepositCaller(contract),
57+
contract: always(contract),
5558
}
5659
}

lib/ethereum/lockup/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ describe('lockup/index.ts', () => {
104104
depositToProperty: createDepositToPropertyCaller(contract),
105105
depositToPosition: createDepositToPositionCaller(contract),
106106
migrateToSTokens: createMigrateToSTokensCaller(contract),
107+
contract: () => contract,
107108
}
108109
}
109110

lib/ethereum/lockup/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { createDepositToPositionCaller } from './depositToPosition'
1919
import { createMigrateToSTokensCaller } from './migrateToSTokens'
2020
import { FallbackableOverrides } from '../../common/utils/execute'
2121
import { TransactionResponse } from '@ethersproject/abstract-provider'
22+
import { always } from 'ramda'
2223

2324
export type LockupContract = {
2425
readonly getValue: (
@@ -72,6 +73,7 @@ export type LockupContract = {
7273
positionTokenId: string,
7374
overrides?: FallbackableOverrides
7475
) => Promise<TransactionResponse>
76+
readonly contract: () => ethers.Contract
7577
}
7678

7779
export const createLockupContract =
@@ -100,5 +102,6 @@ export const createLockupContract =
100102
depositToProperty: createDepositToPropertyCaller(contract),
101103
depositToPosition: createDepositToPositionCaller(contract),
102104
migrateToSTokens: createMigrateToSTokensCaller(contract),
105+
contract: always(contract),
103106
}
104107
}

lib/ethereum/market-behavior/index.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ describe('getId/index.ts', () => {
2525
return {
2626
getId: createGetIdCaller(contract),
2727
getMetrics: createGetMetricsCaller(contract),
28+
contract: () => contract,
2829
}
2930
}
3031

0 commit comments

Comments
 (0)