@agoric/fast-usdc 0.1.1-dev-a035a67.0 → 0.1.1-dev-decd4ff.0
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/package.json +9 -9
- package/src/pool-share-math.js +4 -1
- package/src/type-guards.js +37 -18
- package/src/types.ts +15 -4
- package/src/utils/fees.js +87 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/fast-usdc",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-decd4ff.0+decd4ff",
|
|
4
4
|
"description": "CLI and library for Fast USDC product",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
"ts-blank-space": "^0.4.4"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@agoric/client-utils": "0.1.1-dev-
|
|
33
|
-
"@agoric/cosmic-proto": "0.4.1-dev-
|
|
34
|
-
"@agoric/ertp": "0.16.3-dev-
|
|
35
|
-
"@agoric/internal": "0.3.3-dev-
|
|
36
|
-
"@agoric/notifier": "0.6.3-dev-
|
|
37
|
-
"@agoric/orchestration": "0.1.1-dev-
|
|
38
|
-
"@agoric/zoe": "0.26.3-dev-
|
|
32
|
+
"@agoric/client-utils": "0.1.1-dev-decd4ff.0+decd4ff",
|
|
33
|
+
"@agoric/cosmic-proto": "0.4.1-dev-decd4ff.0+decd4ff",
|
|
34
|
+
"@agoric/ertp": "0.16.3-dev-decd4ff.0+decd4ff",
|
|
35
|
+
"@agoric/internal": "0.3.3-dev-decd4ff.0+decd4ff",
|
|
36
|
+
"@agoric/notifier": "0.6.3-dev-decd4ff.0+decd4ff",
|
|
37
|
+
"@agoric/orchestration": "0.1.1-dev-decd4ff.0+decd4ff",
|
|
38
|
+
"@agoric/zoe": "0.26.3-dev-decd4ff.0+decd4ff",
|
|
39
39
|
"@cosmjs/proto-signing": "^0.33.0",
|
|
40
40
|
"@cosmjs/stargate": "^0.33.0",
|
|
41
41
|
"@endo/base64": "^1.0.9",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"publishConfig": {
|
|
76
76
|
"access": "public"
|
|
77
77
|
},
|
|
78
|
-
"gitHead": "
|
|
78
|
+
"gitHead": "decd4fff2577c63c48facbadb8f9ea45080a5e11"
|
|
79
79
|
}
|
package/src/pool-share-math.js
CHANGED
|
@@ -218,7 +218,10 @@ export const repayCalc = (shareWorth, split, encumberedBalance, poolStats) => {
|
|
|
218
218
|
...poolStats,
|
|
219
219
|
totalRepays: add(poolStats.totalRepays, split.Principal),
|
|
220
220
|
totalPoolFees: add(poolStats.totalPoolFees, split.PoolFee),
|
|
221
|
-
totalContractFees: add(
|
|
221
|
+
totalContractFees: add(
|
|
222
|
+
add(poolStats.totalContractFees, split.ContractFee),
|
|
223
|
+
split.RelayFee,
|
|
224
|
+
),
|
|
222
225
|
},
|
|
223
226
|
});
|
|
224
227
|
};
|
package/src/type-guards.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { AmountShape, BrandShape, RatioShape } from '@agoric/ertp';
|
|
2
2
|
import { M } from '@endo/patterns';
|
|
3
3
|
import {
|
|
4
|
-
CosmosChainInfoShape,
|
|
5
4
|
DenomDetailShape,
|
|
6
5
|
DenomShape,
|
|
7
6
|
} from '@agoric/orchestration/src/typeGuards.js';
|
|
@@ -10,7 +9,7 @@ import { PendingTxStatus } from './constants.js';
|
|
|
10
9
|
/**
|
|
11
10
|
* @import {Amount, Brand, NatValue, Payment} from '@agoric/ertp';
|
|
12
11
|
* @import {TypedPattern} from '@agoric/internal';
|
|
13
|
-
* @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount, IBCConnectionInfo} from '@agoric/orchestration';
|
|
12
|
+
* @import {CosmosChainInfo, Denom, DenomDetail, OrchestrationAccount, IBCConnectionInfo, CaipChainId} from '@agoric/orchestration';
|
|
14
13
|
* @import {USDCProposalShapes} from './pool-share-math.js';
|
|
15
14
|
* @import {CctpTxEvidence, FastUSDCConfig, FastUsdcTerms, FeeConfig, PendingTx, PoolMetrics, ChainPolicy, FeedPolicy, AddressHook, EvmAddress, EvmHash, RiskAssessment, EvidenceWithRisk} from './types.js';
|
|
16
15
|
*/
|
|
@@ -110,13 +109,33 @@ export const AddressHookShape = {
|
|
|
110
109
|
harden(AddressHookShape);
|
|
111
110
|
|
|
112
111
|
const NatAmountShape = { brand: BrandShape, value: M.nat() };
|
|
112
|
+
|
|
113
|
+
export const DestinationOverridesShape = M.recordOf(
|
|
114
|
+
M.string(),
|
|
115
|
+
M.splitRecord(
|
|
116
|
+
{},
|
|
117
|
+
{
|
|
118
|
+
flat: NatAmountShape,
|
|
119
|
+
variableRate: RatioShape,
|
|
120
|
+
contractRate: RatioShape,
|
|
121
|
+
relay: NatAmountShape,
|
|
122
|
+
},
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
|
|
113
126
|
/** @type {TypedPattern<FeeConfig>} */
|
|
114
|
-
export const FeeConfigShape =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
127
|
+
export const FeeConfigShape = M.splitRecord(
|
|
128
|
+
{
|
|
129
|
+
flat: NatAmountShape,
|
|
130
|
+
variableRate: RatioShape,
|
|
131
|
+
contractRate: RatioShape,
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
relay: NatAmountShape,
|
|
135
|
+
destinationOverrides: DestinationOverridesShape,
|
|
136
|
+
},
|
|
137
|
+
{},
|
|
138
|
+
);
|
|
120
139
|
|
|
121
140
|
/** @type {TypedPattern<PoolMetrics>} */
|
|
122
141
|
export const PoolMetricsShape = {
|
|
@@ -162,16 +181,6 @@ export const FeedPolicyShape = M.splitRecord(
|
|
|
162
181
|
);
|
|
163
182
|
harden(FeedPolicyShape);
|
|
164
183
|
|
|
165
|
-
/** @type {TypedPattern<FastUSDCConfig>} */
|
|
166
|
-
export const FastUSDCConfigShape = M.splitRecord({
|
|
167
|
-
terms: FastUSDCTermsShape,
|
|
168
|
-
oracles: M.recordOf(M.string(), M.string()),
|
|
169
|
-
feeConfig: FeeConfigShape,
|
|
170
|
-
feedPolicy: FeedPolicyShape,
|
|
171
|
-
chainInfo: M.recordOf(M.string(), CosmosChainInfoShape),
|
|
172
|
-
assetInfo: M.arrayOf([DenomShape, DenomDetailShape]),
|
|
173
|
-
});
|
|
174
|
-
|
|
175
184
|
/**
|
|
176
185
|
* The version of CosmosChainInfoShape that matches the `valueShape` used in FUSDC's ChainHub's `chainInfos` mapStore.
|
|
177
186
|
* @type {TypedPattern<CosmosChainInfo>}
|
|
@@ -189,3 +198,13 @@ export const CosmosChainInfoShapeV1 = M.splitRecord(
|
|
|
189
198
|
pfmEnabled: M.boolean(),
|
|
190
199
|
},
|
|
191
200
|
);
|
|
201
|
+
|
|
202
|
+
/** @type {TypedPattern<FastUSDCConfig>} */
|
|
203
|
+
export const FastUSDCConfigShape = M.splitRecord({
|
|
204
|
+
terms: FastUSDCTermsShape,
|
|
205
|
+
oracles: M.recordOf(M.string(), M.string()),
|
|
206
|
+
feeConfig: FeeConfigShape,
|
|
207
|
+
feedPolicy: FeedPolicyShape,
|
|
208
|
+
chainInfo: M.recordOf(M.string(), CosmosChainInfoShapeV1),
|
|
209
|
+
assetInfo: M.arrayOf([DenomShape, DenomDetailShape]),
|
|
210
|
+
});
|
package/src/types.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
DenomDetail,
|
|
8
8
|
BaseChainInfo,
|
|
9
9
|
KnownNamespace,
|
|
10
|
+
CaipChainId,
|
|
10
11
|
} from '@agoric/orchestration';
|
|
11
12
|
import type { IBCChannelID } from '@agoric/vats';
|
|
12
13
|
import type { Amount } from '@agoric/ertp';
|
|
@@ -42,7 +43,7 @@ export interface CctpTxEvidence {
|
|
|
42
43
|
/** from Noble RPC */
|
|
43
44
|
aux: {
|
|
44
45
|
forwardingChannel: IBCChannelID;
|
|
45
|
-
recipientAddress: CosmosChainAddress['value'];
|
|
46
|
+
recipientAddress: CosmosChainAddress['value'] | AccountId;
|
|
46
47
|
};
|
|
47
48
|
/** on the source chain (e.g. L1 Ethereum and L2s Arbitrum, Base) */
|
|
48
49
|
blockHash: EvmHash;
|
|
@@ -98,12 +99,22 @@ export interface PendingTx extends CctpTxEvidence {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
export type FeeConfig = {
|
|
101
|
-
/** flat fee charged for every advance */
|
|
102
|
+
/** flat fee charged for every advance, eligible for LP disbursement */
|
|
102
103
|
flat: Amount<'nat'>;
|
|
103
|
-
/** proportion of advance kept as a fee */
|
|
104
|
+
/** proportion of advance kept as a fee, eligible for LP disbursement */
|
|
104
105
|
variableRate: Ratio;
|
|
105
|
-
/** proportion of fees that goes to the contract (remaining goes to LPs) */
|
|
106
|
+
/** proportion of `flat` and `variableRate` fees that goes to the contract (remaining goes to LPs) */
|
|
106
107
|
contractRate: Ratio;
|
|
108
|
+
/**
|
|
109
|
+
* if present, a fee required to relay (e.g. CCTP to EVM/Solana). Not
|
|
110
|
+
* considered for LP disbursement - goes to `contractSeat`.
|
|
111
|
+
*/
|
|
112
|
+
relay?: Amount<'nat'>;
|
|
113
|
+
/** Optional destination-specific overrides. If present, must supersede base values. */
|
|
114
|
+
destinationOverrides?: Record<
|
|
115
|
+
CaipChainId,
|
|
116
|
+
Partial<Omit<FeeConfig, 'destinationOverrides'>>
|
|
117
|
+
>;
|
|
107
118
|
};
|
|
108
119
|
|
|
109
120
|
export interface PoolStats {
|
package/src/utils/fees.js
CHANGED
|
@@ -2,12 +2,14 @@ import { AmountMath } from '@agoric/ertp';
|
|
|
2
2
|
import { multiplyBy } from '@agoric/ertp/src/ratio.js';
|
|
3
3
|
import { Fail } from '@endo/errors';
|
|
4
4
|
import { mustMatch } from '@endo/patterns';
|
|
5
|
+
import { chainOfAccount } from '@agoric/orchestration/src/utils/address.js';
|
|
5
6
|
import { FeeConfigShape } from '../type-guards.js';
|
|
6
7
|
|
|
7
|
-
const { add, isGTE, subtract } = AmountMath;
|
|
8
|
+
const { add, isGTE, subtract, makeEmpty } = AmountMath;
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* @import {Amount} from '@agoric/ertp';
|
|
12
|
+
* @import {AccountId} from '@agoric/orchestration';
|
|
11
13
|
* @import {FeeConfig} from '../types.js';
|
|
12
14
|
*/
|
|
13
15
|
|
|
@@ -16,6 +18,7 @@ const { add, isGTE, subtract } = AmountMath;
|
|
|
16
18
|
* Principal: Amount<'nat'>;
|
|
17
19
|
* PoolFee: Amount<'nat'>;
|
|
18
20
|
* ContractFee: Amount<'nat'>;
|
|
21
|
+
* RelayFee: Amount<'nat'>;
|
|
19
22
|
* }} RepayAmountKWR
|
|
20
23
|
*/
|
|
21
24
|
|
|
@@ -24,48 +27,116 @@ const { add, isGTE, subtract } = AmountMath;
|
|
|
24
27
|
* Principal: Payment<'nat'>;
|
|
25
28
|
* PoolFee: Payment<'nat'>;
|
|
26
29
|
* ContractFee: Payment<'nat'>;
|
|
30
|
+
* RelayFee: Payment<'nat'>;
|
|
27
31
|
* }} RepayPaymentKWR
|
|
28
32
|
*/
|
|
29
33
|
|
|
30
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* @template {keyof Omit<FeeConfig, 'destinationOverrides'>} K
|
|
36
|
+
* @param {FeeConfig} feeConfig
|
|
37
|
+
* @param {K} key
|
|
38
|
+
* @param {AccountId} destination
|
|
39
|
+
* @returns {FeeConfig[K]}
|
|
40
|
+
*/
|
|
41
|
+
const getConfigValue = (feeConfig, key, destination) => {
|
|
42
|
+
const chainId = chainOfAccount(destination);
|
|
43
|
+
if (
|
|
44
|
+
feeConfig.destinationOverrides?.[chainId] &&
|
|
45
|
+
feeConfig.destinationOverrides[chainId][key] !== undefined
|
|
46
|
+
) {
|
|
47
|
+
return feeConfig.destinationOverrides[chainId][key];
|
|
48
|
+
}
|
|
49
|
+
return feeConfig[key];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {FeeConfig} feeConfig
|
|
54
|
+
*/
|
|
31
55
|
export const makeFeeTools = feeConfig => {
|
|
32
56
|
mustMatch(feeConfig, FeeConfigShape, 'Must provide feeConfig');
|
|
33
|
-
const
|
|
57
|
+
const emptyAmount = makeEmpty(feeConfig.flat.brand);
|
|
58
|
+
|
|
34
59
|
const feeTools = harden({
|
|
35
60
|
/**
|
|
36
|
-
* Calculate the
|
|
61
|
+
* Calculate the base fee to charge for the advance (variable + flat).
|
|
62
|
+
* Will be shared between the pool and the contract based on
|
|
63
|
+
* {@link FeeConfig.contractRate}.
|
|
37
64
|
*
|
|
38
65
|
* @param {Amount<'nat'>} requested
|
|
39
|
-
* @
|
|
66
|
+
* @param {AccountId} destination
|
|
67
|
+
* @returns {Amount<'nat'>}
|
|
40
68
|
*/
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
|
|
69
|
+
calculateBaseFee(requested, destination) {
|
|
70
|
+
const flat = getConfigValue(feeConfig, 'flat', destination);
|
|
71
|
+
const variableRate = getConfigValue(
|
|
72
|
+
feeConfig,
|
|
73
|
+
'variableRate',
|
|
74
|
+
destination,
|
|
75
|
+
);
|
|
76
|
+
return add(multiplyBy(requested, variableRate), flat);
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Calculate the optional relay fee charged for certain destinations.
|
|
80
|
+
* Only disbursed to contract seat.
|
|
81
|
+
*
|
|
82
|
+
* @param {AccountId} destination
|
|
83
|
+
* @returns {Amount<'nat'>}
|
|
84
|
+
*/
|
|
85
|
+
calculateRelayFee(destination) {
|
|
86
|
+
const relay = getConfigValue(feeConfig, 'relay', destination);
|
|
87
|
+
return relay || emptyAmount;
|
|
44
88
|
},
|
|
45
89
|
/**
|
|
46
90
|
* Calculate the total fee to charge for the advance.
|
|
47
91
|
*
|
|
48
92
|
* @param {Amount<'nat'>} requested
|
|
93
|
+
* @param {AccountId} destination
|
|
49
94
|
* @throws {Error} if requested does not exceed fees
|
|
50
95
|
*/
|
|
51
|
-
calculateAdvanceFee(requested) {
|
|
52
|
-
const
|
|
96
|
+
calculateAdvanceFee(requested, destination) {
|
|
97
|
+
const baseFee = feeTools.calculateBaseFee(requested, destination);
|
|
98
|
+
const relayFee = feeTools.calculateRelayFee(destination);
|
|
99
|
+
const fee = add(baseFee, relayFee);
|
|
53
100
|
!isGTE(fee, requested) || Fail`Request must exceed fees.`;
|
|
54
101
|
return fee;
|
|
55
102
|
},
|
|
103
|
+
/**
|
|
104
|
+
* Calculate the net amount to advance after withholding fees.
|
|
105
|
+
*
|
|
106
|
+
* @param {Amount<'nat'>} requested
|
|
107
|
+
* @param {AccountId} destination
|
|
108
|
+
* @throws {Error} if requested does not exceed fees
|
|
109
|
+
*/
|
|
110
|
+
calculateAdvance(requested, destination) {
|
|
111
|
+
const fee = feeTools.calculateAdvanceFee(requested, destination);
|
|
112
|
+
return subtract(requested, fee);
|
|
113
|
+
},
|
|
56
114
|
/**
|
|
57
115
|
* Calculate the split of fees between pool and contract.
|
|
58
116
|
*
|
|
117
|
+
* The `ContractFee` includes base fees plus the relay fee.
|
|
118
|
+
*
|
|
59
119
|
* @param {Amount<'nat'>} requested
|
|
120
|
+
* @param {AccountId} destination
|
|
60
121
|
* @returns {RepayAmountKWR} an {@link AmountKeywordRecord}
|
|
61
122
|
* @throws {Error} if requested does not exceed fees
|
|
62
123
|
*/
|
|
63
|
-
calculateSplit(requested) {
|
|
64
|
-
const
|
|
65
|
-
const
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
124
|
+
calculateSplit(requested, destination) {
|
|
125
|
+
const baseFee = feeTools.calculateBaseFee(requested, destination);
|
|
126
|
+
const relayFee = feeTools.calculateRelayFee(destination);
|
|
127
|
+
const totalFee = add(baseFee, relayFee);
|
|
128
|
+
!isGTE(totalFee, requested) || Fail`Request must exceed fees.`;
|
|
129
|
+
|
|
130
|
+
const contractRate = getConfigValue(
|
|
131
|
+
feeConfig,
|
|
132
|
+
'contractRate',
|
|
133
|
+
destination,
|
|
134
|
+
);
|
|
135
|
+
const Principal = subtract(requested, totalFee);
|
|
136
|
+
const ContractFee = multiplyBy(baseFee, contractRate);
|
|
137
|
+
const PoolFee = subtract(baseFee, ContractFee);
|
|
138
|
+
|
|
139
|
+
return harden({ Principal, PoolFee, ContractFee, RelayFee: relayFee });
|
|
69
140
|
},
|
|
70
141
|
});
|
|
71
142
|
return feeTools;
|