@agoric/fast-usdc 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-other-dev-fbe72e7.0.fbe72e7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -36
- package/package.json +39 -38
- package/src/cli/bridge-action.js +40 -0
- package/src/cli/cli.js +47 -154
- package/src/cli/config-commands.js +108 -0
- package/src/cli/config.js +15 -9
- package/src/cli/lp-commands.js +160 -0
- package/src/cli/operator-commands.js +143 -0
- package/src/cli/transfer.js +81 -21
- package/src/cli/util/agoric.js +11 -0
- package/src/cli/util/bank.js +12 -0
- package/src/{util → cli/util}/cctp.js +1 -1
- package/src/{util → cli/util}/file.js +1 -1
- package/src/clientSupport.js +98 -0
- package/src/constants.js +29 -6
- package/src/main.js +1 -0
- package/src/operator-kit-interface.js +29 -0
- package/src/pool-share-math.js +72 -34
- package/src/type-guards.js +122 -34
- package/src/types.ts +136 -15
- package/src/utils/fees.js +105 -20
- package/tools/cli-tools.ts +9 -0
- package/tools/mock-evidence.ts +205 -0
- package/tools/mock-io.ts +14 -0
- package/src/exos/README.md +0 -26
- package/src/exos/advancer.js +0 -255
- package/src/exos/liquidity-pool.js +0 -365
- package/src/exos/operator-kit.js +0 -120
- package/src/exos/settler.js +0 -97
- package/src/exos/status-manager.js +0 -176
- package/src/exos/transaction-feed.js +0 -180
- package/src/fast-usdc.contract.js +0 -235
- package/src/fast-usdc.flows.js +0 -13
- package/src/fast-usdc.start.js +0 -284
- package/src/util/agoric.js +0 -12
- package/src/utils/address.js +0 -71
- package/src/utils/config-marshal.js +0 -130
- package/src/utils/zoe.js +0 -28
- /package/src/{util → cli/util}/noble.js +0 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
import { assertAllDefined } from '@agoric/internal';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @import {USDCProposalShapes} from './pool-share-math.js';
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {Pick<
|
|
10
|
+
* import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
|
|
11
|
+
* 'brand'
|
|
12
|
+
* >} agoricNames
|
|
13
|
+
* @param {object} opts
|
|
14
|
+
* @param {string} opts.offerId
|
|
15
|
+
* @param {bigint} opts.fastLPAmount
|
|
16
|
+
* @param {bigint} opts.usdcAmount
|
|
17
|
+
* @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec & {proposal: USDCProposalShapes['deposit']}}
|
|
18
|
+
*/
|
|
19
|
+
const makeDepositOffer = ({ brand }, { offerId, fastLPAmount, usdcAmount }) => {
|
|
20
|
+
assertAllDefined({ offerId, fastLPAmount, usdcAmount });
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
id: offerId,
|
|
24
|
+
invitationSpec: {
|
|
25
|
+
source: 'agoricContract',
|
|
26
|
+
instancePath: ['fastUsdc'],
|
|
27
|
+
callPipe: [['makeDepositInvitation']],
|
|
28
|
+
},
|
|
29
|
+
/** @type {USDCProposalShapes['deposit']} */
|
|
30
|
+
// @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
|
|
31
|
+
proposal: {
|
|
32
|
+
give: {
|
|
33
|
+
USDC: {
|
|
34
|
+
brand: brand.USDC,
|
|
35
|
+
value: usdcAmount,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
want: {
|
|
39
|
+
PoolShare: {
|
|
40
|
+
brand: brand.FastLP,
|
|
41
|
+
value: fastLPAmount,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {Pick<
|
|
50
|
+
* import('@agoric/vats/tools/board-utils.js').AgoricNamesRemotes,
|
|
51
|
+
* 'brand'
|
|
52
|
+
* >} agoricNames
|
|
53
|
+
* @param {object} opts
|
|
54
|
+
* @param {string} opts.offerId
|
|
55
|
+
* @param {bigint} opts.fastLPAmount
|
|
56
|
+
* @param {bigint} opts.usdcAmount
|
|
57
|
+
* @returns {import('@agoric/smart-wallet/src/offers.js').OfferSpec}
|
|
58
|
+
*/
|
|
59
|
+
const makeWithdrawOffer = (
|
|
60
|
+
{ brand },
|
|
61
|
+
{ offerId, fastLPAmount, usdcAmount },
|
|
62
|
+
) => ({
|
|
63
|
+
id: offerId,
|
|
64
|
+
invitationSpec: {
|
|
65
|
+
source: 'agoricContract',
|
|
66
|
+
instancePath: ['fastUsdc'],
|
|
67
|
+
callPipe: [['makeWithdrawInvitation']],
|
|
68
|
+
},
|
|
69
|
+
proposal: {
|
|
70
|
+
give: {
|
|
71
|
+
PoolShare: {
|
|
72
|
+
// @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
|
|
73
|
+
brand: brand.FastLP,
|
|
74
|
+
value: fastLPAmount,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
want: {
|
|
78
|
+
USDC: {
|
|
79
|
+
// @ts-expect-error https://github.com/Agoric/agoric-sdk/issues/10491
|
|
80
|
+
brand: brand.USDC,
|
|
81
|
+
value: usdcAmount,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @satisfies {Record<
|
|
89
|
+
* string,
|
|
90
|
+
* Record<string, import('@agoric/smart-wallet/src/types.js').OfferMaker>
|
|
91
|
+
* >}
|
|
92
|
+
*/
|
|
93
|
+
export const Offers = {
|
|
94
|
+
fastUsdc: {
|
|
95
|
+
Deposit: makeDepositOffer,
|
|
96
|
+
Withdraw: makeWithdrawOffer,
|
|
97
|
+
},
|
|
98
|
+
};
|
package/src/constants.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Status values for FastUSDC.
|
|
2
|
+
* Status values for FastUSDC. Includes states for advancing and settling.
|
|
3
3
|
*
|
|
4
4
|
* @enum {(typeof TxStatus)[keyof typeof TxStatus]}
|
|
5
5
|
*/
|
|
@@ -7,21 +7,44 @@ export const TxStatus = /** @type {const} */ ({
|
|
|
7
7
|
/** tx was observed but not advanced */
|
|
8
8
|
Observed: 'OBSERVED',
|
|
9
9
|
/** IBC transfer is initiated */
|
|
10
|
+
Advancing: 'ADVANCING',
|
|
11
|
+
/** IBC transfer is complete */
|
|
10
12
|
Advanced: 'ADVANCED',
|
|
11
|
-
/**
|
|
12
|
-
|
|
13
|
+
/** IBC transfer failed (timed out) */
|
|
14
|
+
AdvanceFailed: 'ADVANCE_FAILED',
|
|
15
|
+
/** Advance skipped and waiting for forward */
|
|
16
|
+
AdvanceSkipped: 'ADVANCE_SKIPPED',
|
|
17
|
+
/** settlement for matching advance received and funds disbursed */
|
|
18
|
+
Disbursed: 'DISBURSED',
|
|
19
|
+
/** No route, forward not attempted */
|
|
20
|
+
ForwardedSkipped: 'FORWARD_SKIPPED',
|
|
21
|
+
/** fallback: do not collect fees */
|
|
22
|
+
Forwarded: 'FORWARDED',
|
|
23
|
+
/** failed to forward to EUD */
|
|
24
|
+
ForwardFailed: 'FORWARD_FAILED',
|
|
13
25
|
});
|
|
14
26
|
harden(TxStatus);
|
|
15
27
|
|
|
28
|
+
// According to the state diagram
|
|
29
|
+
export const TerminalTxStatus = {
|
|
30
|
+
[TxStatus.Forwarded]: true,
|
|
31
|
+
[TxStatus.ForwardFailed]: true,
|
|
32
|
+
[TxStatus.Disbursed]: true,
|
|
33
|
+
};
|
|
34
|
+
|
|
16
35
|
/**
|
|
17
|
-
* Status values for the StatusManager.
|
|
36
|
+
* Status values for the StatusManager while an advance is being processed.
|
|
18
37
|
*
|
|
19
38
|
* @enum {(typeof PendingTxStatus)[keyof typeof PendingTxStatus]}
|
|
20
39
|
*/
|
|
21
40
|
export const PendingTxStatus = /** @type {const} */ ({
|
|
22
|
-
/** tx was observed but not advanced */
|
|
23
|
-
Observed: 'OBSERVED',
|
|
24
41
|
/** IBC transfer is initiated */
|
|
42
|
+
Advancing: 'ADVANCING',
|
|
43
|
+
/** IBC transfer failed (timed out) */
|
|
44
|
+
AdvanceFailed: 'ADVANCE_FAILED',
|
|
45
|
+
/** IBC transfer is complete */
|
|
25
46
|
Advanced: 'ADVANCED',
|
|
47
|
+
/** Advance skipped and waiting for forward */
|
|
48
|
+
AdvanceSkipped: 'ADVANCE_SKIPPED',
|
|
26
49
|
});
|
|
27
50
|
harden(PendingTxStatus);
|
package/src/main.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './types.js';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { M } from '@endo/patterns';
|
|
2
|
+
import { CctpTxEvidenceShape, RiskAssessmentShape } from './type-guards.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @import {Zone} from '@agoric/zone';
|
|
6
|
+
* @import {CctpTxEvidence, RiskAssessment} from '@agoric/fast-usdc/src/types.js';
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/** Name in the invitation purse (keyed also by this contract instance) */
|
|
10
|
+
export const INVITATION_MAKERS_DESC = 'oracle operator invitation';
|
|
11
|
+
|
|
12
|
+
export const OperatorKitI = {
|
|
13
|
+
admin: M.interface('Admin', {
|
|
14
|
+
disable: M.call().returns(),
|
|
15
|
+
}),
|
|
16
|
+
|
|
17
|
+
invitationMakers: M.interface('InvitationMakers', {
|
|
18
|
+
SubmitEvidence: M.call(CctpTxEvidenceShape)
|
|
19
|
+
.optional(RiskAssessmentShape)
|
|
20
|
+
.returns(M.promise()),
|
|
21
|
+
}),
|
|
22
|
+
|
|
23
|
+
operator: M.interface('Operator', {
|
|
24
|
+
submitEvidence: M.call(CctpTxEvidenceShape)
|
|
25
|
+
.optional(RiskAssessmentShape)
|
|
26
|
+
.returns(),
|
|
27
|
+
getStatus: M.call().returns(M.record()),
|
|
28
|
+
}),
|
|
29
|
+
};
|
package/src/pool-share-math.js
CHANGED
|
@@ -4,21 +4,23 @@ import {
|
|
|
4
4
|
makeRatio,
|
|
5
5
|
makeRatioFromAmounts,
|
|
6
6
|
multiplyBy,
|
|
7
|
-
} from '@agoric/
|
|
7
|
+
} from '@agoric/ertp/src/ratio.js';
|
|
8
8
|
import { Fail, q } from '@endo/errors';
|
|
9
9
|
|
|
10
|
-
const {
|
|
10
|
+
const { keys } = Object;
|
|
11
|
+
const { add, isEmpty, isEqual, isGTE, make, makeEmpty, subtract } = AmountMath;
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
* @import {
|
|
14
|
-
* @import {
|
|
14
|
+
* @import {Amount, Brand, DepositFacet, NatValue, Payment, Ratio} from '@agoric/ertp';
|
|
15
|
+
* @import {Allocation} from '@agoric/zoe';
|
|
16
|
+
* @import {PoolStats} from './types.js';
|
|
17
|
+
* @import {RepayAmountKWR} from './utils/fees.js';
|
|
15
18
|
*/
|
|
16
19
|
|
|
17
20
|
/**
|
|
18
21
|
* Invariant: shareWorth is the pool balance divided by shares outstanding.
|
|
19
22
|
*
|
|
20
|
-
* Use `makeParity(
|
|
21
|
-
* value, for some negligible `epsilon` such as 1n.
|
|
23
|
+
* Use `makeParity(USDC, PoolShares)` for an initial value.
|
|
22
24
|
*
|
|
23
25
|
* @typedef {Ratio} ShareWorth
|
|
24
26
|
*/
|
|
@@ -26,23 +28,26 @@ const { getValue, add, isEmpty, isEqual, isGTE, subtract } = AmountMath;
|
|
|
26
28
|
/**
|
|
27
29
|
* Make a 1-to-1 ratio between amounts of 2 brands.
|
|
28
30
|
*
|
|
29
|
-
* @param {
|
|
31
|
+
* @param {Brand<'nat'>} numeratorBrand
|
|
30
32
|
* @param {Brand<'nat'>} denominatorBrand
|
|
31
33
|
*/
|
|
32
|
-
export const makeParity = (
|
|
33
|
-
const
|
|
34
|
-
return makeRatio(
|
|
34
|
+
export const makeParity = (numeratorBrand, denominatorBrand) => {
|
|
35
|
+
const dust = 1n;
|
|
36
|
+
return makeRatio(dust, numeratorBrand, dust, denominatorBrand);
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
40
|
* @typedef {{
|
|
39
41
|
* deposit: {
|
|
40
42
|
* give: { USDC: Amount<'nat'> },
|
|
41
|
-
* want
|
|
43
|
+
* want: { PoolShare: Amount<'nat'> }
|
|
42
44
|
* },
|
|
43
45
|
* withdraw: {
|
|
44
46
|
* give: { PoolShare: Amount<'nat'> }
|
|
45
47
|
* want: { USDC: Amount<'nat'> },
|
|
48
|
+
* },
|
|
49
|
+
* withdrawFees: {
|
|
50
|
+
* want: { USDC: Amount<'nat'> }
|
|
46
51
|
* }
|
|
47
52
|
* }} USDCProposalShapes
|
|
48
53
|
*/
|
|
@@ -91,14 +96,54 @@ export const depositCalc = (shareWorth, { give, want }) => {
|
|
|
91
96
|
});
|
|
92
97
|
};
|
|
93
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Verifies that the total pool balance (unencumbered + encumbered) matches the
|
|
101
|
+
* shareWorth numerator. The total pool balance consists of:
|
|
102
|
+
* 1. unencumbered balance - USDC available in the pool for borrowing
|
|
103
|
+
* 2. encumbered balance - USDC currently lent out
|
|
104
|
+
*
|
|
105
|
+
* A negligible `dust` amount is used to initialize shareWorth with a non-zero
|
|
106
|
+
* denominator. It must remain in the pool at all times.
|
|
107
|
+
*
|
|
108
|
+
* @param {Allocation} poolAlloc
|
|
109
|
+
* @param {ShareWorth} shareWorth
|
|
110
|
+
* @param {Amount<'nat'>} encumberedBalance
|
|
111
|
+
*/
|
|
112
|
+
export const checkPoolBalance = (poolAlloc, shareWorth, encumberedBalance) => {
|
|
113
|
+
const { brand: usdcBrand } = encumberedBalance;
|
|
114
|
+
const unencumberedBalance = poolAlloc.USDC || makeEmpty(usdcBrand);
|
|
115
|
+
const kwds = keys(poolAlloc);
|
|
116
|
+
kwds.length === 0 ||
|
|
117
|
+
(kwds.length === 1 && kwds[0] === 'USDC') ||
|
|
118
|
+
Fail`unexpected pool allocations: ${poolAlloc}`;
|
|
119
|
+
const dust = make(usdcBrand, 1n);
|
|
120
|
+
const grossBalance = add(add(unencumberedBalance, dust), encumberedBalance);
|
|
121
|
+
isEqual(grossBalance, shareWorth.numerator) ||
|
|
122
|
+
Fail`🚨 pool balance ${q(unencumberedBalance)} and encumbered balance ${q(encumberedBalance)} inconsistent with shareWorth ${q(shareWorth)}`;
|
|
123
|
+
return harden({ unencumberedBalance, grossBalance });
|
|
124
|
+
};
|
|
125
|
+
|
|
94
126
|
/**
|
|
95
127
|
* Compute payout from a withdraw proposal, along with updated shareWorth
|
|
96
128
|
*
|
|
97
129
|
* @param {ShareWorth} shareWorth
|
|
98
130
|
* @param {USDCProposalShapes['withdraw']} proposal
|
|
131
|
+
* @param {Allocation} poolAlloc
|
|
132
|
+
* @param {Amount<'nat'>} [encumberedBalance]
|
|
99
133
|
* @returns {{ shareWorth: ShareWorth, payouts: { USDC: Amount<'nat'> }}}
|
|
100
134
|
*/
|
|
101
|
-
export const withdrawCalc = (
|
|
135
|
+
export const withdrawCalc = (
|
|
136
|
+
shareWorth,
|
|
137
|
+
{ give, want },
|
|
138
|
+
poolAlloc,
|
|
139
|
+
encumberedBalance = makeEmpty(shareWorth.numerator.brand),
|
|
140
|
+
) => {
|
|
141
|
+
const { unencumberedBalance } = checkPoolBalance(
|
|
142
|
+
poolAlloc,
|
|
143
|
+
shareWorth,
|
|
144
|
+
encumberedBalance,
|
|
145
|
+
);
|
|
146
|
+
|
|
102
147
|
assert(!isEmpty(give.PoolShare));
|
|
103
148
|
assert(!isEmpty(want.USDC));
|
|
104
149
|
|
|
@@ -108,6 +153,8 @@ export const withdrawCalc = (shareWorth, { give, want }) => {
|
|
|
108
153
|
const { denominator: sharesOutstanding, numerator: poolBalance } = shareWorth;
|
|
109
154
|
!isGTE(want.USDC, poolBalance) ||
|
|
110
155
|
Fail`cannot withdraw ${q(want.USDC)}; only ${q(poolBalance)} in pool`;
|
|
156
|
+
isGTE(unencumberedBalance, want.USDC) ||
|
|
157
|
+
Fail`cannot withdraw ${q(want.USDC)}; ${q(encumberedBalance)} is in use; stand by for pool to return to ${q(poolBalance)}`;
|
|
111
158
|
const balancePost = subtract(poolBalance, payout);
|
|
112
159
|
// giving more shares than are outstanding is impossible,
|
|
113
160
|
// so it's not worth a custom diagnostic. subtract will fail
|
|
@@ -155,35 +202,26 @@ export const borrowCalc = (
|
|
|
155
202
|
|
|
156
203
|
/**
|
|
157
204
|
* @param {ShareWorth} shareWorth
|
|
158
|
-
* @param {
|
|
159
|
-
* @param {RepayAmountKWR} amounts
|
|
205
|
+
* @param {RepayAmountKWR} split
|
|
160
206
|
* @param {Amount<'nat'>} encumberedBalance aka 'outstanding borrows'
|
|
161
207
|
* @param {PoolStats} poolStats
|
|
162
|
-
* @throws {Error} if
|
|
208
|
+
* @throws {Error} if Principal exceeds encumberedBalance
|
|
163
209
|
*/
|
|
164
|
-
export const repayCalc = (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
amounts,
|
|
168
|
-
encumberedBalance,
|
|
169
|
-
poolStats,
|
|
170
|
-
) => {
|
|
171
|
-
(isEqual(fromSeatAllocation.Principal, amounts.Principal) &&
|
|
172
|
-
isEqual(fromSeatAllocation.PoolFee, amounts.PoolFee) &&
|
|
173
|
-
isEqual(fromSeatAllocation.ContractFee, amounts.ContractFee)) ||
|
|
174
|
-
Fail`Cannot repay. From seat allocation ${q(fromSeatAllocation)} does not equal amounts ${q(amounts)}.`;
|
|
175
|
-
|
|
176
|
-
isGTE(encumberedBalance, amounts.Principal) ||
|
|
177
|
-
Fail`Cannot repay. Principal ${q(amounts.Principal)} exceeds encumberedBalance ${q(encumberedBalance)}.`;
|
|
210
|
+
export const repayCalc = (shareWorth, split, encumberedBalance, poolStats) => {
|
|
211
|
+
isGTE(encumberedBalance, split.Principal) ||
|
|
212
|
+
Fail`Cannot repay. Principal ${q(split.Principal)} exceeds encumberedBalance ${q(encumberedBalance)}.`;
|
|
178
213
|
|
|
179
214
|
return harden({
|
|
180
|
-
shareWorth: withFees(shareWorth,
|
|
181
|
-
encumberedBalance: subtract(encumberedBalance,
|
|
215
|
+
shareWorth: withFees(shareWorth, split.PoolFee),
|
|
216
|
+
encumberedBalance: subtract(encumberedBalance, split.Principal),
|
|
182
217
|
poolStats: {
|
|
183
218
|
...poolStats,
|
|
184
|
-
totalRepays: add(poolStats.totalRepays,
|
|
185
|
-
totalPoolFees: add(poolStats.totalPoolFees,
|
|
186
|
-
totalContractFees: add(
|
|
219
|
+
totalRepays: add(poolStats.totalRepays, split.Principal),
|
|
220
|
+
totalPoolFees: add(poolStats.totalPoolFees, split.PoolFee),
|
|
221
|
+
totalContractFees: add(
|
|
222
|
+
add(poolStats.totalContractFees, split.ContractFee),
|
|
223
|
+
split.RelayFee,
|
|
224
|
+
),
|
|
187
225
|
},
|
|
188
226
|
});
|
|
189
227
|
};
|
package/src/type-guards.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { AmountShape, BrandShape, RatioShape } from '@agoric/ertp';
|
|
2
2
|
import { M } from '@endo/patterns';
|
|
3
|
+
import {
|
|
4
|
+
DenomDetailShape,
|
|
5
|
+
DenomShape,
|
|
6
|
+
} from '@agoric/orchestration/src/typeGuards.js';
|
|
3
7
|
import { PendingTxStatus } from './constants.js';
|
|
4
8
|
|
|
5
9
|
/**
|
|
10
|
+
* @import {Amount, Brand, NatValue, Payment} from '@agoric/ertp';
|
|
6
11
|
* @import {TypedPattern} from '@agoric/internal';
|
|
7
|
-
* @import {
|
|
12
|
+
* @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount, IBCConnectionInfo, CaipChainId} from '@agoric/orchestration';
|
|
8
13
|
* @import {USDCProposalShapes} from './pool-share-math.js';
|
|
9
|
-
* @import {CctpTxEvidence, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy} from './types.js';
|
|
14
|
+
* @import {CctpTxEvidence, FastUSDCConfig, FastUsdcTerms, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash, RiskAssessment, EvidenceWithRisk} from './types.js';
|
|
10
15
|
*/
|
|
11
16
|
|
|
12
17
|
/**
|
|
13
|
-
* @param {Brand} brand must be a 'nat' brand, not checked
|
|
18
|
+
* @param {Brand<'nat'>} brand must be a 'nat' brand, not checked
|
|
14
19
|
* @param {NatValue} [min]
|
|
15
20
|
*/
|
|
16
21
|
export const makeNatAmountShape = (brand, min) =>
|
|
@@ -19,16 +24,20 @@ export const makeNatAmountShape = (brand, min) =>
|
|
|
19
24
|
/** @param {Record<'PoolShares' | 'USDC', Brand<'nat'>>} brands */
|
|
20
25
|
export const makeProposalShapes = ({ PoolShares, USDC }) => {
|
|
21
26
|
/** @type {TypedPattern<USDCProposalShapes['deposit']>} */
|
|
22
|
-
const deposit = M.splitRecord(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
);
|
|
27
|
+
const deposit = M.splitRecord({
|
|
28
|
+
give: { USDC: makeNatAmountShape(USDC, 1n) },
|
|
29
|
+
want: { PoolShare: makeNatAmountShape(PoolShares) },
|
|
30
|
+
});
|
|
26
31
|
/** @type {TypedPattern<USDCProposalShapes['withdraw']>} */
|
|
27
32
|
const withdraw = M.splitRecord({
|
|
28
33
|
give: { PoolShare: makeNatAmountShape(PoolShares, 1n) },
|
|
29
34
|
want: { USDC: makeNatAmountShape(USDC, 1n) },
|
|
30
35
|
});
|
|
31
|
-
|
|
36
|
+
/** @type {TypedPattern<USDCProposalShapes['withdrawFees']>} */
|
|
37
|
+
const withdrawFees = M.splitRecord({
|
|
38
|
+
want: { USDC: makeNatAmountShape(USDC, 1n) },
|
|
39
|
+
});
|
|
40
|
+
return harden({ deposit, withdraw, withdrawFees });
|
|
32
41
|
};
|
|
33
42
|
|
|
34
43
|
/** @type {TypedPattern<FastUsdcTerms>} */
|
|
@@ -36,12 +45,28 @@ export const FastUSDCTermsShape = harden({
|
|
|
36
45
|
usdcDenom: M.string(),
|
|
37
46
|
});
|
|
38
47
|
|
|
39
|
-
/** @type {TypedPattern<
|
|
48
|
+
/** @type {TypedPattern<EvmAddress>} */
|
|
49
|
+
export const EvmAddressShape = M.string({
|
|
50
|
+
// 0x + 40 hex digits
|
|
51
|
+
stringLengthLimit: 42,
|
|
52
|
+
});
|
|
53
|
+
harden(EvmAddressShape);
|
|
54
|
+
|
|
55
|
+
/** @type {TypedPattern<EvmHash>} */
|
|
40
56
|
export const EvmHashShape = M.string({
|
|
41
57
|
stringLengthLimit: 66,
|
|
42
58
|
});
|
|
43
59
|
harden(EvmHashShape);
|
|
44
60
|
|
|
61
|
+
/** @type {TypedPattern<RiskAssessment>} */
|
|
62
|
+
export const RiskAssessmentShape = M.splitRecord(
|
|
63
|
+
{},
|
|
64
|
+
{
|
|
65
|
+
risksIdentified: M.arrayOf(M.string()),
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
harden(RiskAssessmentShape);
|
|
69
|
+
|
|
45
70
|
/** @type {TypedPattern<CctpTxEvidence>} */
|
|
46
71
|
export const CctpTxEvidenceShape = {
|
|
47
72
|
aux: {
|
|
@@ -49,17 +74,25 @@ export const CctpTxEvidenceShape = {
|
|
|
49
74
|
recipientAddress: M.string(),
|
|
50
75
|
},
|
|
51
76
|
blockHash: EvmHashShape,
|
|
52
|
-
blockNumber: M.
|
|
53
|
-
blockTimestamp: M.
|
|
77
|
+
blockNumber: M.nat(),
|
|
78
|
+
blockTimestamp: M.nat(),
|
|
54
79
|
chainId: M.number(),
|
|
55
80
|
tx: {
|
|
56
|
-
amount: M.
|
|
81
|
+
amount: M.nat(),
|
|
57
82
|
forwardingAddress: M.string(),
|
|
83
|
+
sender: EvmAddressShape,
|
|
58
84
|
},
|
|
59
85
|
txHash: EvmHashShape,
|
|
60
86
|
};
|
|
61
87
|
harden(CctpTxEvidenceShape);
|
|
62
88
|
|
|
89
|
+
/** @type {TypedPattern<EvidenceWithRisk>} */
|
|
90
|
+
export const EvidenceWithRiskShape = {
|
|
91
|
+
evidence: CctpTxEvidenceShape,
|
|
92
|
+
risk: RiskAssessmentShape,
|
|
93
|
+
};
|
|
94
|
+
harden(EvidenceWithRiskShape);
|
|
95
|
+
|
|
63
96
|
/** @type {TypedPattern<PendingTx>} */
|
|
64
97
|
// @ts-expect-error TypedPattern not recognized as record
|
|
65
98
|
export const PendingTxShape = {
|
|
@@ -68,20 +101,42 @@ export const PendingTxShape = {
|
|
|
68
101
|
};
|
|
69
102
|
harden(PendingTxShape);
|
|
70
103
|
|
|
71
|
-
|
|
72
|
-
|
|
104
|
+
/** @type {TypedPattern<AddressHook>} */
|
|
105
|
+
export const AddressHookShape = {
|
|
106
|
+
baseAddress: M.string(),
|
|
107
|
+
query: { EUD: M.string() },
|
|
73
108
|
};
|
|
74
|
-
harden(
|
|
109
|
+
harden(AddressHookShape);
|
|
75
110
|
|
|
76
111
|
const NatAmountShape = { brand: BrandShape, value: M.nat() };
|
|
112
|
+
|
|
113
|
+
/** @type {TypedPattern<FeeConfig['destinationOverrides']>} */
|
|
114
|
+
export const DestinationOverridesShape = M.recordOf(
|
|
115
|
+
M.string(),
|
|
116
|
+
M.splitRecord(
|
|
117
|
+
{},
|
|
118
|
+
{
|
|
119
|
+
flat: NatAmountShape,
|
|
120
|
+
variableRate: RatioShape,
|
|
121
|
+
contractRate: RatioShape,
|
|
122
|
+
relay: NatAmountShape,
|
|
123
|
+
},
|
|
124
|
+
),
|
|
125
|
+
);
|
|
126
|
+
|
|
77
127
|
/** @type {TypedPattern<FeeConfig>} */
|
|
78
|
-
export const FeeConfigShape =
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
128
|
+
export const FeeConfigShape = M.splitRecord(
|
|
129
|
+
{
|
|
130
|
+
flat: NatAmountShape,
|
|
131
|
+
variableRate: RatioShape,
|
|
132
|
+
contractRate: RatioShape,
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
relay: NatAmountShape,
|
|
136
|
+
destinationOverrides: DestinationOverridesShape,
|
|
137
|
+
},
|
|
138
|
+
{},
|
|
139
|
+
);
|
|
85
140
|
|
|
86
141
|
/** @type {TypedPattern<PoolMetrics>} */
|
|
87
142
|
export const PoolMetricsShape = {
|
|
@@ -95,29 +150,62 @@ export const PoolMetricsShape = {
|
|
|
95
150
|
harden(PoolMetricsShape);
|
|
96
151
|
|
|
97
152
|
/** @type {TypedPattern<ChainPolicy>} */
|
|
98
|
-
export const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
153
|
+
export const ChainPolicyShape = {
|
|
154
|
+
attenuatedCttpBridgeAddresses: M.splitArray(
|
|
155
|
+
[EvmHashShape],
|
|
156
|
+
undefined,
|
|
157
|
+
M.arrayOf(EvmHashShape),
|
|
158
|
+
),
|
|
159
|
+
cctpTokenMessengerAddress: EvmHashShape,
|
|
160
|
+
confirmations: M.number(),
|
|
161
|
+
chainId: M.number(),
|
|
162
|
+
rateLimits: {
|
|
163
|
+
tx: M.bigint(),
|
|
164
|
+
blockWindow: M.bigint(),
|
|
165
|
+
blockWindowSize: M.number(),
|
|
104
166
|
},
|
|
105
|
-
|
|
106
|
-
);
|
|
107
|
-
harden(ChainPoliciesShape);
|
|
167
|
+
};
|
|
168
|
+
harden(ChainPolicyShape);
|
|
108
169
|
|
|
109
170
|
/**
|
|
110
171
|
* @type {TypedPattern<FeedPolicy>}
|
|
111
172
|
*
|
|
112
|
-
*
|
|
113
|
-
* undefined, remotable, etc.
|
|
173
|
+
* must be CopyData; no Brands or other Remotables
|
|
114
174
|
*/
|
|
115
175
|
export const FeedPolicyShape = M.splitRecord(
|
|
116
176
|
{
|
|
117
177
|
nobleDomainId: M.number(),
|
|
118
178
|
nobleAgoricChannelId: M.string(),
|
|
119
|
-
chainPolicies: M.recordOf(M.string(),
|
|
179
|
+
chainPolicies: M.recordOf(M.string(), ChainPolicyShape),
|
|
120
180
|
},
|
|
121
181
|
{ eventFilter: M.string() },
|
|
122
182
|
);
|
|
123
183
|
harden(FeedPolicyShape);
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* The version of CosmosChainInfoShape that matches the `valueShape` used in FUSDC's ChainHub's `chainInfos` mapStore.
|
|
187
|
+
* @type {TypedPattern<CosmosChainInfo>}
|
|
188
|
+
*/
|
|
189
|
+
export const CosmosChainInfoShapeV1 = M.splitRecord(
|
|
190
|
+
{
|
|
191
|
+
chainId: M.string(),
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
bech32Prefix: M.string(),
|
|
195
|
+
connections: M.record(),
|
|
196
|
+
stakingTokens: M.arrayOf({ denom: M.string() }),
|
|
197
|
+
// UNTIL https://github.com/Agoric/agoric-sdk/issues/9326
|
|
198
|
+
icqEnabled: M.boolean(),
|
|
199
|
+
pfmEnabled: M.boolean(),
|
|
200
|
+
},
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
/** @type {TypedPattern<FastUSDCConfig>} */
|
|
204
|
+
export const FastUSDCConfigShape = M.splitRecord({
|
|
205
|
+
terms: FastUSDCTermsShape,
|
|
206
|
+
oracles: M.recordOf(M.string(), M.string()),
|
|
207
|
+
feeConfig: FeeConfigShape,
|
|
208
|
+
feedPolicy: FeedPolicyShape,
|
|
209
|
+
chainInfo: M.recordOf(M.string(), CosmosChainInfoShapeV1),
|
|
210
|
+
assetInfo: M.arrayOf([DenomShape, DenomDetailShape]),
|
|
211
|
+
});
|