@agoric/fast-usdc 0.1.1-dev-cf1d435.0 → 0.1.1-dev-d6a7ffb.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 CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.1.1-dev-cf1d435.0+cf1d435",
3
+ "version": "0.1.1-dev-d6a7ffb.0+d6a7ffb",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "contract",
8
- "src"
8
+ "src",
9
+ "tools"
9
10
  ],
10
11
  "bin": {
11
12
  "fast-usdc": "./src/cli/bin.js"
@@ -21,9 +22,9 @@
21
22
  "lint:eslint": "eslint ."
22
23
  },
23
24
  "devDependencies": {
24
- "@agoric/swingset-liveslots": "0.10.3-dev-cf1d435.0+cf1d435",
25
- "@agoric/vats": "0.15.2-dev-cf1d435.0+cf1d435",
26
- "@agoric/zone": "0.2.3-dev-cf1d435.0+cf1d435",
25
+ "@agoric/swingset-liveslots": "0.10.3-dev-d6a7ffb.0+d6a7ffb",
26
+ "@agoric/vats": "0.15.2-dev-d6a7ffb.0+d6a7ffb",
27
+ "@agoric/zone": "0.2.3-dev-d6a7ffb.0+d6a7ffb",
27
28
  "@fast-check/ava": "^2.0.1",
28
29
  "ava": "^5.3.0",
29
30
  "c8": "^10.1.2",
@@ -31,15 +32,15 @@
31
32
  "ts-blank-space": "^0.4.1"
32
33
  },
33
34
  "dependencies": {
34
- "@agoric/client-utils": "0.1.1-dev-cf1d435.0+cf1d435",
35
- "@agoric/ertp": "0.16.3-dev-cf1d435.0+cf1d435",
36
- "@agoric/internal": "0.3.3-dev-cf1d435.0+cf1d435",
37
- "@agoric/notifier": "0.6.3-dev-cf1d435.0+cf1d435",
38
- "@agoric/orchestration": "0.1.1-dev-cf1d435.0+cf1d435",
39
- "@agoric/store": "0.9.3-dev-cf1d435.0+cf1d435",
40
- "@agoric/vat-data": "0.5.3-dev-cf1d435.0+cf1d435",
41
- "@agoric/vow": "0.1.1-dev-cf1d435.0+cf1d435",
42
- "@agoric/zoe": "0.26.3-dev-cf1d435.0+cf1d435",
35
+ "@agoric/client-utils": "0.1.1-dev-d6a7ffb.0+d6a7ffb",
36
+ "@agoric/ertp": "0.16.3-dev-d6a7ffb.0+d6a7ffb",
37
+ "@agoric/internal": "0.3.3-dev-d6a7ffb.0+d6a7ffb",
38
+ "@agoric/notifier": "0.6.3-dev-d6a7ffb.0+d6a7ffb",
39
+ "@agoric/orchestration": "0.1.1-dev-d6a7ffb.0+d6a7ffb",
40
+ "@agoric/store": "0.9.3-dev-d6a7ffb.0+d6a7ffb",
41
+ "@agoric/vat-data": "0.5.3-dev-d6a7ffb.0+d6a7ffb",
42
+ "@agoric/vow": "0.1.1-dev-d6a7ffb.0+d6a7ffb",
43
+ "@agoric/zoe": "0.26.3-dev-d6a7ffb.0+d6a7ffb",
43
44
  "@cosmjs/proto-signing": "^0.32.4",
44
45
  "@cosmjs/stargate": "^0.32.4",
45
46
  "@endo/base64": "^1.0.9",
@@ -49,6 +50,7 @@
49
50
  "@endo/far": "^1.1.9",
50
51
  "@endo/init": "^1.1.7",
51
52
  "@endo/marshal": "^1.6.2",
53
+ "@endo/nat": "^5.0.13",
52
54
  "@endo/pass-style": "^1.4.7",
53
55
  "@endo/patterns": "^1.4.7",
54
56
  "@endo/promise-kit": "^1.1.8",
@@ -78,5 +80,5 @@
78
80
  "publishConfig": {
79
81
  "access": "public"
80
82
  },
81
- "gitHead": "cf1d43515a2a014b0b53cf18935eea5136ae73e2"
83
+ "gitHead": "d6a7ffb6290c63287c4e1fda66d188440105c2a7"
82
84
  }
package/src/cli/cli.js CHANGED
@@ -1,3 +1,5 @@
1
+ /* eslint-env node */
2
+ /* global globalThis */
1
3
  import { assertParsableNumber } from '@agoric/zoe/src/contractSupport/ratio.js';
2
4
  import {
3
5
  Command,
@@ -34,6 +36,11 @@ export const initProgram = (
34
36
  writeFile = writeAsync,
35
37
  mkdir = mkdirSync,
36
38
  exists = existsSync,
39
+ fetch = globalThis.fetch,
40
+ stdout = process.stdout,
41
+ stderr = process.stderr,
42
+ env = process.env,
43
+ now = () => Date.now(),
37
44
  ) => {
38
45
  const program = new Command();
39
46
 
@@ -55,8 +62,27 @@ export const initProgram = (
55
62
  return makeFile(getConfigPath(), readFile, writeFile, mkdir, exists);
56
63
  };
57
64
 
65
+ program.addHelpText(
66
+ 'afterAll',
67
+ `
68
+ Agoric test networks provide configuration info at, for example,
69
+
70
+ https://devnet.agoric.net/network-config
71
+
72
+ To use RPC endpoints from such a configuration, use:
73
+ export AGORIC_NET=devnet
74
+
75
+ Use AGORIC_NET=local or leave it unset to use localhost and chain id agoriclocal.
76
+ `,
77
+ );
58
78
  addConfigCommands(program, configHelpers, makeConfigFile);
59
- addOperatorCommands(program);
79
+ addOperatorCommands(program, {
80
+ fetch,
81
+ stdout,
82
+ stderr,
83
+ env,
84
+ now,
85
+ });
60
86
 
61
87
  /** @param {string} value */
62
88
  const parseDecimal = value => {
package/src/cli/config.js CHANGED
@@ -6,7 +6,6 @@ import { stdin as input, stdout as output } from 'node:process';
6
6
  nobleSeed: string,
7
7
  ethSeed: string,
8
8
  nobleToAgoricChannel: string,
9
- agoricRpc: string,
10
9
  nobleApi: string,
11
10
  nobleRpc: string,
12
11
  ethRpc: string,
@@ -1,18 +1,44 @@
1
- /* eslint-env node */
2
1
  /**
3
2
  * @import {Command} from 'commander';
4
3
  * @import {OfferSpec} from '@agoric/smart-wallet/src/offers.js';
5
4
  * @import {ExecuteOfferAction} from '@agoric/smart-wallet/src/smartWallet.js';
5
+ * @import {OperatorKit} from '../exos/operator-kit.js';
6
6
  */
7
7
 
8
8
  import { fetchEnvNetworkConfig, makeVstorageKit } from '@agoric/client-utils';
9
+ import { mustMatch } from '@agoric/internal';
10
+ import { Nat } from '@endo/nat';
11
+ import { InvalidArgumentError } from 'commander';
9
12
  import { INVITATION_MAKERS_DESC } from '../exos/transaction-feed.js';
13
+ import { CctpTxEvidenceShape } from '../type-guards.js';
10
14
  import { outputActionAndHint } from './bridge-action.js';
11
15
 
16
+ /** @param {string} arg */
17
+ const parseNat = arg => {
18
+ const n = Nat(BigInt(arg));
19
+ return n;
20
+ };
21
+
22
+ /** @param {string} arg */
23
+ const parseHex = arg => {
24
+ if (!arg.startsWith('0x')) throw new InvalidArgumentError('not a hex string');
25
+ return arg;
26
+ };
27
+
12
28
  /**
13
29
  * @param {Command} program
30
+ * @param {{
31
+ * fetch: Window['fetch'];
32
+ * stdout: typeof process.stdout;
33
+ * stderr: typeof process.stderr;
34
+ * env: typeof process.env;
35
+ * now: typeof Date.now;
36
+ * }} io
14
37
  */
15
- export const addOperatorCommands = program => {
38
+ export const addOperatorCommands = (
39
+ program,
40
+ { fetch, stderr, stdout, env, now },
41
+ ) => {
16
42
  const operator = program
17
43
  .command('operator')
18
44
  .description('Oracle operator commands');
@@ -24,17 +50,9 @@ export const addOperatorCommands = program => {
24
50
  'after',
25
51
  '\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"',
26
52
  )
27
- .option(
28
- '--offerId <string>',
29
- 'Offer id',
30
- String,
31
- `operatorAccept-${Date.now()}`,
32
- )
53
+ .option('--offerId <string>', 'Offer id', String, `operatorAccept-${now()}`)
33
54
  .action(async opts => {
34
- const networkConfig = await fetchEnvNetworkConfig({
35
- env: process.env,
36
- fetch,
37
- });
55
+ const networkConfig = await fetchEnvNetworkConfig({ env, fetch });
38
56
  const vsk = await makeVstorageKit({ fetch }, networkConfig);
39
57
  const instance = vsk.agoricNames.instance.fastUsdc;
40
58
  assert(instance, 'fastUsdc instance not in agoricNames');
@@ -56,21 +74,58 @@ export const addOperatorCommands = program => {
56
74
  offer,
57
75
  };
58
76
 
59
- outputActionAndHint(bridgeAction, {
60
- stderr: process.stderr,
61
- stdout: process.stdout,
62
- });
77
+ outputActionAndHint(bridgeAction, { stderr, stdout });
63
78
  });
64
79
 
65
80
  operator
66
81
  .command('attest')
67
82
  .description('Attest to an observed Fast USDC transfer')
68
83
  .requiredOption('--previousOfferId <string>', 'Offer id', String)
69
- .action(async options => {
70
- const { previousOfferId } = options;
71
- console.error(
72
- 'TODO: Implement attest logic for request:',
84
+ .requiredOption('--forwardingChannel <string>', 'Channel id', String)
85
+ .requiredOption('--recipientAddress <string>', 'bech32 address', String)
86
+ .requiredOption('--blockHash <0xhex>', 'hex hash', parseHex)
87
+ .requiredOption('--blockNumber <number>', 'number', parseNat)
88
+ .requiredOption('--blockTimestamp <number>', 'number', parseNat)
89
+ .requiredOption('--chainId <string>', 'chain id', Number)
90
+ .requiredOption('--amount <number>', 'number', parseNat)
91
+ .requiredOption('--forwardingAddress <string>', 'bech32 address', String)
92
+ .requiredOption('--txHash <0xhexo>', 'hex hash', parseHex)
93
+ .option('--offerId <string>', 'Offer id', String, `operatorAttest-${now()}`)
94
+ .action(async opts => {
95
+ const {
96
+ offerId,
73
97
  previousOfferId,
98
+ forwardingChannel,
99
+ recipientAddress,
100
+ amount,
101
+ forwardingAddress,
102
+ ...flat
103
+ } = opts;
104
+
105
+ const evidence = harden({
106
+ aux: { forwardingChannel, recipientAddress },
107
+ tx: { amount, forwardingAddress },
108
+ ...flat,
109
+ });
110
+ mustMatch(evidence, CctpTxEvidenceShape);
111
+
112
+ /** @type {OfferSpec} */
113
+ const offer = {
114
+ id: offerId,
115
+ invitationSpec: {
116
+ source: 'continuing',
117
+ previousOffer: previousOfferId,
118
+ /** @type {string & keyof OperatorKit['invitationMakers'] } */
119
+ invitationMakerName: 'SubmitEvidence',
120
+ /** @type {Parameters<OperatorKit['invitationMakers']['SubmitEvidence']> } */
121
+ invitationArgs: [evidence],
122
+ },
123
+ proposal: {},
124
+ };
125
+
126
+ outputActionAndHint(
127
+ { method: 'executeOffer', offer },
128
+ { stderr, stdout },
74
129
  );
75
130
  });
76
131
 
@@ -1,13 +1,18 @@
1
+ /* eslint-env node */
1
2
  /* global globalThis */
2
3
 
3
- import { makeVStorage } from '@agoric/client-utils';
4
+ import {
5
+ fetchEnvNetworkConfig,
6
+ makeVStorage,
7
+ pickEndpoint,
8
+ } from '@agoric/client-utils';
9
+ import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
4
10
  import { depositForBurn, makeProvider } from '../util/cctp.js';
5
11
  import {
6
12
  makeSigner,
7
13
  queryForwardingAccount,
8
14
  registerFwdAccount,
9
15
  } from '../util/noble.js';
10
- import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
11
16
 
12
17
  /** @import { File } from '../util/file' */
13
18
  /** @import { VStorage } from '@agoric/client-utils' */
@@ -23,13 +28,15 @@ const transfer = async (
23
28
  /** @type {VStorage | undefined} */ vstorage,
24
29
  /** @type {{signer: SigningStargateClient, address: string} | undefined} */ nobleSigner,
25
30
  /** @type {ethProvider | undefined} */ ethProvider,
31
+ env = process.env,
26
32
  ) => {
27
33
  const execute = async (
28
34
  /** @type {import('./config').ConfigOpts} */ config,
29
35
  ) => {
36
+ const netConfig = await fetchEnvNetworkConfig({ env, fetch });
30
37
  vstorage ||= makeVStorage(
31
38
  { fetch },
32
- { chainName: 'agoric', rpcAddrs: [config.agoricRpc] },
39
+ { chainName: 'agoric', rpcAddrs: [pickEndpoint(netConfig)] },
33
40
  );
34
41
  const agoricAddr = await queryFastUSDCLocalChainAccount(vstorage, out);
35
42
  const appendedAddr = `${agoricAddr}?EUD=${destination}`;
@@ -0,0 +1,9 @@
1
+ export const flags = (
2
+ record: Record<string, string | number | bigint | undefined>,
3
+ ): string[] => {
4
+ // @ts-expect-error undefined is filtered out
5
+ const skipUndef: [string, string][] = Object.entries(record).filter(
6
+ ([_k, v]) => v !== undefined,
7
+ );
8
+ return skipUndef.map(([k, v]) => [`--${k}`, `${v}`]).flat();
9
+ };
@@ -0,0 +1,14 @@
1
+ import type { Writable } from 'node:stream';
2
+
3
+ /**
4
+ * mock stdout / stderr, for example
5
+ *
6
+ * @param buf - caller-provided buffer for written data
7
+ */
8
+ export const mockStream = <T extends Writable>(buf: string[]): T =>
9
+ ({
10
+ write: txt => {
11
+ buf.push(txt);
12
+ return true;
13
+ },
14
+ }) as T;