@agoric/fast-usdc 0.1.1-other-dev-3eb1a1d.0 → 0.1.1-upgrade-19-dev-c605745.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.
Files changed (40) hide show
  1. package/README.md +43 -0
  2. package/package.json +29 -25
  3. package/src/add-operators.core.js +63 -0
  4. package/src/cli/bridge-action.js +40 -0
  5. package/src/cli/cli.js +46 -153
  6. package/src/cli/config-commands.js +108 -0
  7. package/src/cli/config.js +15 -9
  8. package/src/cli/lp-commands.js +160 -0
  9. package/src/cli/operator-commands.js +146 -0
  10. package/src/cli/transfer.js +63 -13
  11. package/src/{util → cli/util}/agoric.js +1 -1
  12. package/src/cli/util/bank.js +12 -0
  13. package/src/{util → cli/util}/cctp.js +1 -1
  14. package/src/{util → cli/util}/file.js +1 -1
  15. package/src/clientSupport.js +98 -0
  16. package/src/constants.js +25 -2
  17. package/src/distribute-fees.core.js +93 -0
  18. package/src/exos/advancer.js +220 -106
  19. package/src/exos/liquidity-pool.js +130 -81
  20. package/src/exos/operator-kit.js +16 -12
  21. package/src/exos/settler.js +360 -64
  22. package/src/exos/status-manager.js +316 -65
  23. package/src/exos/transaction-feed.js +121 -42
  24. package/src/fast-usdc-policy.core.js +65 -0
  25. package/src/fast-usdc.contract.js +165 -84
  26. package/src/fast-usdc.flows.js +10 -0
  27. package/src/main.js +1 -0
  28. package/src/pool-share-math.js +55 -9
  29. package/src/{fast-usdc.start.js → start-fast-usdc.core.js} +48 -86
  30. package/src/type-guards.js +75 -24
  31. package/src/types.ts +89 -14
  32. package/src/utils/chain-policies.js +140 -0
  33. package/src/utils/core-eval.js +73 -0
  34. package/src/utils/deploy-config.js +127 -0
  35. package/src/utils/fees.js +3 -4
  36. package/tools/cli-tools.ts +9 -0
  37. package/tools/mock-io.ts +14 -0
  38. package/src/exos/README.md +0 -26
  39. package/src/utils/address.js +0 -71
  40. /package/src/{util → cli/util}/noble.js +0 -0
@@ -0,0 +1,160 @@
1
+ /* eslint-env node */
2
+ /**
3
+ * @import {Command} from 'commander';
4
+ * @import {Amount, Brand} from '@agoric/ertp';
5
+ * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
6
+ * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
7
+ * @import {USDCProposalShapes} from '../pool-share-math.js';
8
+ */
9
+
10
+ import {
11
+ fetchEnvNetworkConfig,
12
+ makeSmartWalletKit,
13
+ } from '@agoric/client-utils';
14
+ import { AmountMath } from '@agoric/ertp';
15
+ import {
16
+ assertParsableNumber,
17
+ ceilDivideBy,
18
+ floorDivideBy,
19
+ multiplyBy,
20
+ parseRatio,
21
+ } from '@agoric/zoe/src/contractSupport/ratio.js';
22
+ import { InvalidArgumentError } from 'commander';
23
+ import { outputActionAndHint } from './bridge-action.js';
24
+ import { Offers } from '../clientSupport.js';
25
+
26
+ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
27
+
28
+ /** @param {string} arg */
29
+ const parseDecimal = arg => {
30
+ try {
31
+ assertParsableNumber(arg);
32
+ const n = Number(arg);
33
+ return n;
34
+ } catch {
35
+ throw new InvalidArgumentError('Not a number');
36
+ }
37
+ };
38
+
39
+ /**
40
+ * @param {string} amountString
41
+ * @param {Brand} usdc
42
+ */
43
+ const parseUSDCAmount = (amountString, usdc) => {
44
+ const USDC_DECIMALS = 6;
45
+ const unit = AmountMath.make(usdc, 10n ** BigInt(USDC_DECIMALS));
46
+ return multiplyBy(unit, parseRatio(amountString, usdc));
47
+ };
48
+
49
+ /**
50
+ * @param {Command} program
51
+ * @param {{
52
+ * fetch?: Window['fetch'];
53
+ * smartWalletKit?: import('@agoric/client-utils').SmartWalletKit;
54
+ * stdout: typeof process.stdout;
55
+ * stderr: typeof process.stderr;
56
+ * env: typeof process.env;
57
+ * now: typeof Date.now;
58
+ * }} io
59
+ */
60
+ export const addLPCommands = (
61
+ program,
62
+ { fetch, smartWalletKit, stderr, stdout, env, now },
63
+ ) => {
64
+ const loadSwk = async () => {
65
+ if (smartWalletKit) {
66
+ return smartWalletKit;
67
+ }
68
+ assert(fetch);
69
+ const networkConfig = await fetchEnvNetworkConfig({ env, fetch });
70
+ return makeSmartWalletKit({ delay, fetch }, networkConfig);
71
+ };
72
+ /** @type {undefined | ReturnType<typeof loadSwk>} */
73
+ let swkP;
74
+
75
+ program
76
+ .command('deposit')
77
+ .description('Deposit USDC into pool')
78
+ .addHelpText(
79
+ 'after',
80
+ '\nPipe the STDOUT to a file such as deposit.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer deposit.json --from gov1 --keyring-backend="test"',
81
+ )
82
+ .requiredOption('--amount <number>', 'USDC amount', parseDecimal)
83
+ .option('--offerId <string>', 'Offer id', String, `lpDeposit-${now()}`)
84
+ .action(async opts => {
85
+ swkP ||= loadSwk();
86
+ const swk = await swkP;
87
+
88
+ /** @type {Brand<'nat'>} */
89
+ // @ts-expect-error it doesnt recognize usdc as a Brand type
90
+ const usdc = swk.agoricNames.brand.USDC;
91
+ assert(usdc, 'USDC brand not in agoricNames');
92
+
93
+ /** @type {Brand<'nat'>} */
94
+ // @ts-expect-error it doesnt recognize FastLP as a Brand type
95
+ const poolShare = swk.agoricNames.brand.FastLP;
96
+ assert(poolShare, 'FastLP brand not in agoricNames');
97
+
98
+ const usdcAmount = parseUSDCAmount(opts.amount, usdc);
99
+
100
+ const metrics = await swk.readPublished('fastUsdc.poolMetrics');
101
+ const fastLPAmount = floorDivideBy(usdcAmount, metrics.shareWorth);
102
+
103
+ const offer = Offers.fastUsdc.Deposit(swk.agoricNames, {
104
+ offerId: opts.offerId,
105
+ fastLPAmount: fastLPAmount.value,
106
+ usdcAmount: usdcAmount.value,
107
+ });
108
+
109
+ /** @type {ExecuteOfferAction} */
110
+ const bridgeAction = {
111
+ method: 'executeOffer',
112
+ offer,
113
+ };
114
+
115
+ outputActionAndHint(bridgeAction, { stderr, stdout }, swk.marshaller);
116
+ });
117
+
118
+ program
119
+ .command('withdraw')
120
+ .description("Withdraw USDC from the LP's pool share")
121
+ .addHelpText(
122
+ 'after',
123
+ '\nPipe the STDOUT to a file such as withdraw.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer withdraw.json --from gov1 --keyring-backend="test"',
124
+ )
125
+ .requiredOption('--amount <number>', 'USDC amount', parseDecimal)
126
+ .option('--offerId <string>', 'Offer id', String, `lpWithdraw-${now()}`)
127
+ .action(async opts => {
128
+ swkP ||= loadSwk();
129
+ const swk = await swkP;
130
+
131
+ /** @type {Brand<'nat'>} */
132
+ // @ts-expect-error it doesnt recognize FastLP as a Brand type
133
+ const poolShare = swk.agoricNames.brand.FastLP;
134
+ assert(poolShare, 'FastLP brand not in agoricNames');
135
+
136
+ /** @type {Brand<'nat'>} */
137
+ // @ts-expect-error it doesnt recognize usdc as a Brand type
138
+ const usdc = swk.agoricNames.brand.USDC;
139
+ assert(usdc, 'USDC brand not in agoricNames');
140
+
141
+ const usdcAmount = parseUSDCAmount(opts.amount, usdc);
142
+
143
+ const metrics = await swk.readPublished('fastUsdc.poolMetrics');
144
+ const fastLPAmount = ceilDivideBy(usdcAmount, metrics.shareWorth);
145
+
146
+ const offer = Offers.fastUsdc.Withdraw(swk.agoricNames, {
147
+ offerId: opts.offerId,
148
+ fastLPAmount: fastLPAmount.value,
149
+ usdcAmount: usdcAmount.value,
150
+ });
151
+
152
+ outputActionAndHint(
153
+ { method: 'executeOffer', offer },
154
+ { stderr, stdout },
155
+ swk.marshaller,
156
+ );
157
+ });
158
+
159
+ return program;
160
+ };
@@ -0,0 +1,146 @@
1
+ /* eslint-env node */
2
+ /**
3
+ * @import {Command} from 'commander';
4
+ * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
5
+ * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
6
+ * @import {OperatorKit} from '../exos/operator-kit.js';
7
+ */
8
+
9
+ import {
10
+ fetchEnvNetworkConfig,
11
+ makeSmartWalletKit,
12
+ } from '@agoric/client-utils';
13
+ import { mustMatch } from '@agoric/internal';
14
+ import { Nat } from '@endo/nat';
15
+ import { InvalidArgumentError } from 'commander';
16
+ import { INVITATION_MAKERS_DESC } from '../exos/transaction-feed.js';
17
+ import { CctpTxEvidenceShape } from '../type-guards.js';
18
+ import { outputActionAndHint } from './bridge-action.js';
19
+
20
+ export const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
21
+
22
+ /** @param {string} arg */
23
+ const parseNat = arg => {
24
+ const n = Nat(BigInt(arg));
25
+ return n;
26
+ };
27
+
28
+ /** @param {string} arg */
29
+ const parseHex = arg => {
30
+ if (!arg.startsWith('0x')) throw new InvalidArgumentError('not a hex string');
31
+ return arg;
32
+ };
33
+
34
+ /**
35
+ * @param {Command} program
36
+ * @param {{
37
+ * fetch: Window['fetch'];
38
+ * stdout: typeof process.stdout;
39
+ * stderr: typeof process.stderr;
40
+ * env: typeof process.env;
41
+ * now: typeof Date.now;
42
+ * }} io
43
+ */
44
+ export const addOperatorCommands = (
45
+ program,
46
+ { fetch, stderr, stdout, env, now },
47
+ ) => {
48
+ const operator = program
49
+ .command('operator')
50
+ .description('Oracle operator commands');
51
+
52
+ operator
53
+ .command('accept')
54
+ .description('Accept invitation to be an operator')
55
+ .addHelpText(
56
+ 'after',
57
+ '\nPipe the STDOUT to a file such as accept.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer accept.json --from gov1 --keyring-backend="test"',
58
+ )
59
+ .option('--offerId <string>', 'Offer id', String, `operatorAccept-${now()}`)
60
+ .action(async opts => {
61
+ const networkConfig = await fetchEnvNetworkConfig({ env, fetch });
62
+
63
+ const swk = await makeSmartWalletKit({ delay, fetch }, networkConfig);
64
+ const instance = swk.agoricNames.instance.fastUsdc;
65
+ assert(instance, 'fastUsdc instance not in agoricNames');
66
+
67
+ /** @type {OfferSpec} */
68
+ const offer = {
69
+ id: opts.offerId,
70
+ invitationSpec: {
71
+ source: 'purse',
72
+ instance,
73
+ description: INVITATION_MAKERS_DESC,
74
+ },
75
+ proposal: {},
76
+ };
77
+
78
+ /** @type {ExecuteOfferAction} */
79
+ const bridgeAction = {
80
+ method: 'executeOffer',
81
+ offer,
82
+ };
83
+
84
+ outputActionAndHint(bridgeAction, { stderr, stdout });
85
+ });
86
+
87
+ operator
88
+ .command('attest')
89
+ .description('Attest to an observed Fast USDC transfer')
90
+ .addHelpText(
91
+ 'after',
92
+ '\nPipe the STDOUT to a file such as attest.json, then use the Agoric CLI to broadcast it:\n agoric wallet send --offer attest.json --from gov1 --keyring-backend="test"',
93
+ )
94
+ .requiredOption('--previousOfferId <string>', 'Offer id', String)
95
+ .requiredOption('--forwardingChannel <string>', 'Channel id', String)
96
+ .requiredOption('--recipientAddress <string>', 'bech32 address', String)
97
+ .requiredOption('--blockHash <0xhex>', 'hex hash', parseHex)
98
+ .requiredOption('--blockNumber <number>', 'number', parseNat)
99
+ .requiredOption('--blockTimestamp <number>', 'number', parseNat)
100
+ .requiredOption('--chainId <string>', 'chain id', Number)
101
+ .requiredOption('--amount <number>', 'number', parseNat)
102
+ .requiredOption('--forwardingAddress <string>', 'bech32 address', String)
103
+ .requiredOption('--sender <string>', 'Ethereum address initiating', String)
104
+ .requiredOption('--txHash <0xhexo>', 'hex hash', parseHex)
105
+ .option('--offerId <string>', 'Offer id', String, `operatorAttest-${now()}`)
106
+ .action(async opts => {
107
+ const {
108
+ offerId,
109
+ previousOfferId,
110
+ forwardingChannel,
111
+ recipientAddress,
112
+ amount,
113
+ forwardingAddress,
114
+ sender,
115
+ ...flat
116
+ } = opts;
117
+
118
+ const evidence = harden({
119
+ aux: { forwardingChannel, recipientAddress },
120
+ tx: { amount, forwardingAddress, sender },
121
+ ...flat,
122
+ });
123
+ mustMatch(evidence, CctpTxEvidenceShape);
124
+
125
+ /** @type {OfferSpec} */
126
+ const offer = {
127
+ id: offerId,
128
+ invitationSpec: {
129
+ source: 'continuing',
130
+ previousOffer: previousOfferId,
131
+ /** @type {string & keyof OperatorKit['invitationMakers'] } */
132
+ invitationMakerName: 'SubmitEvidence',
133
+ /** @type {Parameters<OperatorKit['invitationMakers']['SubmitEvidence']> } */
134
+ invitationArgs: [evidence],
135
+ },
136
+ proposal: {},
137
+ };
138
+
139
+ outputActionAndHint(
140
+ { method: 'executeOffer', offer },
141
+ { stderr, stdout },
142
+ );
143
+ });
144
+
145
+ return operator;
146
+ };
@@ -1,44 +1,54 @@
1
+ /* eslint-env node */
1
2
  /* global globalThis */
2
3
 
3
- import { makeVStorage } from '@agoric/client-utils';
4
- import { depositForBurn, makeProvider } from '../util/cctp.js';
4
+ import {
5
+ fetchEnvNetworkConfig,
6
+ makeVStorage,
7
+ pickEndpoint,
8
+ } from '@agoric/client-utils';
9
+ import { encodeAddressHook } from '@agoric/cosmic-proto/address-hooks.js';
10
+ import { queryFastUSDCLocalChainAccount } from './util/agoric.js';
11
+ import { depositForBurn, makeProvider } from './util/cctp.js';
5
12
  import {
6
13
  makeSigner,
7
14
  queryForwardingAccount,
8
15
  registerFwdAccount,
9
- } from '../util/noble.js';
10
- import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
16
+ } from './util/noble.js';
17
+ import { queryUSDCBalance } from './util/bank.js';
11
18
 
12
- /** @import { file } from '../util/file' */
19
+ /** @import { File } from './util/file' */
13
20
  /** @import { VStorage } from '@agoric/client-utils' */
14
21
  /** @import { SigningStargateClient } from '@cosmjs/stargate' */
15
22
  /** @import { JsonRpcProvider as ethProvider } from 'ethers' */
16
23
 
17
24
  const transfer = async (
18
- /** @type {file} */ configFile,
25
+ /** @type {File} */ configFile,
19
26
  /** @type {string} */ amount,
20
- /** @type {string} */ destination,
27
+ /** @type {string} */ EUD,
21
28
  out = console,
22
29
  fetch = globalThis.fetch,
23
30
  /** @type {VStorage | undefined} */ vstorage,
24
31
  /** @type {{signer: SigningStargateClient, address: string} | undefined} */ nobleSigner,
25
32
  /** @type {ethProvider | undefined} */ ethProvider,
33
+ env = process.env,
34
+ setTimeout = globalThis.setTimeout,
26
35
  ) => {
27
36
  const execute = async (
28
37
  /** @type {import('./config').ConfigOpts} */ config,
29
38
  ) => {
39
+ const netConfig = await fetchEnvNetworkConfig({ env, fetch });
30
40
  vstorage ||= makeVStorage(
31
41
  { fetch },
32
- { chainName: 'agoric', rpcAddrs: [config.agoricRpc] },
42
+ { chainName: 'agoric', rpcAddrs: [pickEndpoint(netConfig)] },
33
43
  );
34
44
  const agoricAddr = await queryFastUSDCLocalChainAccount(vstorage, out);
35
- const appendedAddr = `${agoricAddr}?EUD=${destination}`;
36
- out.log(`forwarding destination ${appendedAddr}`);
45
+ const encodedAddr = encodeAddressHook(agoricAddr, { EUD });
46
+ out.log(`forwarding destination ${encodedAddr}`);
37
47
 
38
48
  const { exists, address } = await queryForwardingAccount(
39
49
  config.nobleApi,
40
50
  config.nobleToAgoricChannel,
41
- appendedAddr,
51
+ encodedAddr,
42
52
  out,
43
53
  fetch,
44
54
  );
@@ -51,18 +61,30 @@ const transfer = async (
51
61
  signer,
52
62
  signerAddress,
53
63
  config.nobleToAgoricChannel,
54
- appendedAddr,
64
+ encodedAddr,
55
65
  out,
56
66
  );
57
67
  out.log(res);
58
68
  } catch (e) {
59
69
  out.error(
60
- `Error registering noble forwarding account for ${appendedAddr} on channel ${config.nobleToAgoricChannel}`,
70
+ `Error registering noble forwarding account for ${encodedAddr} on channel ${config.nobleToAgoricChannel}`,
61
71
  );
62
72
  throw e;
63
73
  }
64
74
  }
65
75
 
76
+ const destChain = config.destinationChains?.find(chain =>
77
+ EUD.startsWith(chain.bech32Prefix),
78
+ );
79
+ if (!destChain) {
80
+ out.error(
81
+ `No destination chain found in config with matching bech32 prefix for ${EUD}, cannot query destination address`,
82
+ );
83
+ throw new Error();
84
+ }
85
+ const { api, USDCDenom } = destChain;
86
+ const startingBalance = await queryUSDCBalance(EUD, api, USDCDenom, fetch);
87
+
66
88
  ethProvider ||= makeProvider(config.ethRpc);
67
89
  await depositForBurn(
68
90
  ethProvider,
@@ -73,6 +95,34 @@ const transfer = async (
73
95
  amount,
74
96
  out,
75
97
  );
98
+
99
+ const refreshDelayMS = 1200;
100
+ const completeP = /** @type {Promise<void>} */ (
101
+ new Promise((res, rej) => {
102
+ const refreshUSDCBalance = async () => {
103
+ out.log('polling usdc balance');
104
+ const currentBalance = await queryUSDCBalance(
105
+ EUD,
106
+ api,
107
+ USDCDenom,
108
+ fetch,
109
+ );
110
+ if (currentBalance !== startingBalance) {
111
+ res();
112
+ } else {
113
+ setTimeout(() => refreshUSDCBalance().catch(rej), refreshDelayMS);
114
+ }
115
+ };
116
+ refreshUSDCBalance().catch(rej);
117
+ })
118
+ ).catch(e => {
119
+ out.error(
120
+ 'Error checking destination address balance, could not detect completion of transfer.',
121
+ );
122
+ out.error(e.message);
123
+ });
124
+
125
+ await completeP;
76
126
  };
77
127
 
78
128
  let config;
@@ -5,7 +5,7 @@ export const queryFastUSDCLocalChainAccount = async (
5
5
  out = console,
6
6
  ) => {
7
7
  const agoricAddr = await vstorage.readLatest(
8
- 'published.fastUSDC.settlementAccount',
8
+ 'published.fastUsdc.settlementAccount',
9
9
  );
10
10
  out.log(`Got Fast USDC Local Chain Account ${agoricAddr}`);
11
11
  return agoricAddr;
@@ -0,0 +1,12 @@
1
+ export const queryUSDCBalance = async (
2
+ /** @type {string} */ address,
3
+ /** @type {string} */ api,
4
+ /** @type {string} */ denom,
5
+ /** @type {typeof globalThis.fetch} */ fetch,
6
+ ) => {
7
+ const query = `${api}/cosmos/bank/v1beta1/balances/${address}`;
8
+ const json = await fetch(query).then(res => res.json());
9
+ const amount = json.balances?.find(b => b.denom === denom)?.amount ?? '0';
10
+
11
+ return BigInt(amount);
12
+ };
@@ -67,5 +67,5 @@ export const depositForBurn = async (
67
67
 
68
68
  out.log('Transaction confirmed in block', receipt.blockNumber);
69
69
  out.log('Transaction hash:', receipt.hash);
70
- out.log('USDC transfer initiated successfully, our work here is done.');
70
+ out.log('USDC transfer initiated successfully');
71
71
  };
@@ -27,4 +27,4 @@ export const makeFile = (
27
27
  return { read, write, exists, path };
28
28
  };
29
29
 
30
- /** @typedef {ReturnType<typeof makeFile>} file */
30
+ /** @typedef {ReturnType<typeof makeFile>} File */
@@ -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
@@ -7,12 +7,29 @@ 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
- /** settlement for matching advance received and funds dispersed */
12
- Settled: 'SETTLED',
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
+ /** fallback: do not collect fees */
20
+ Forwarded: 'FORWARDED',
21
+ /** failed to forward to EUD */
22
+ ForwardFailed: 'FORWARD_FAILED',
13
23
  });
14
24
  harden(TxStatus);
15
25
 
26
+ // According to the state diagram
27
+ export const TerminalTxStatus = {
28
+ [TxStatus.Forwarded]: true,
29
+ [TxStatus.ForwardFailed]: true,
30
+ [TxStatus.Disbursed]: true,
31
+ };
32
+
16
33
  /**
17
34
  * Status values for the StatusManager.
18
35
  *
@@ -22,6 +39,12 @@ export const PendingTxStatus = /** @type {const} */ ({
22
39
  /** tx was observed but not advanced */
23
40
  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);