@agoric/fast-usdc 0.1.1-dev-8657c4c.0 → 0.1.1-dev-a2e9363.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.1.1-dev-8657c4c.0+8657c4c",
3
+ "version": "0.1.1-dev-a2e9363.0+a2e9363",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
@@ -21,9 +21,9 @@
21
21
  "lint:eslint": "eslint ."
22
22
  },
23
23
  "devDependencies": {
24
- "@agoric/swingset-liveslots": "0.10.3-dev-8657c4c.0+8657c4c",
25
- "@agoric/vats": "0.15.2-dev-8657c4c.0+8657c4c",
26
- "@agoric/zone": "0.2.3-dev-8657c4c.0+8657c4c",
24
+ "@agoric/swingset-liveslots": "0.10.3-dev-a2e9363.0+a2e9363",
25
+ "@agoric/vats": "0.15.2-dev-a2e9363.0+a2e9363",
26
+ "@agoric/zone": "0.2.3-dev-a2e9363.0+a2e9363",
27
27
  "@fast-check/ava": "^2.0.1",
28
28
  "ava": "^5.3.0",
29
29
  "c8": "^10.1.2",
@@ -31,15 +31,15 @@
31
31
  "ts-blank-space": "^0.4.1"
32
32
  },
33
33
  "dependencies": {
34
- "@agoric/client-utils": "0.1.1-dev-8657c4c.0+8657c4c",
35
- "@agoric/ertp": "0.16.3-dev-8657c4c.0+8657c4c",
36
- "@agoric/internal": "0.3.3-dev-8657c4c.0+8657c4c",
37
- "@agoric/notifier": "0.6.3-dev-8657c4c.0+8657c4c",
38
- "@agoric/orchestration": "0.1.1-dev-8657c4c.0+8657c4c",
39
- "@agoric/store": "0.9.3-dev-8657c4c.0+8657c4c",
40
- "@agoric/vat-data": "0.5.3-dev-8657c4c.0+8657c4c",
41
- "@agoric/vow": "0.1.1-dev-8657c4c.0+8657c4c",
42
- "@agoric/zoe": "0.26.3-dev-8657c4c.0+8657c4c",
34
+ "@agoric/client-utils": "0.1.1-dev-a2e9363.0+a2e9363",
35
+ "@agoric/ertp": "0.16.3-dev-a2e9363.0+a2e9363",
36
+ "@agoric/internal": "0.3.3-dev-a2e9363.0+a2e9363",
37
+ "@agoric/notifier": "0.6.3-dev-a2e9363.0+a2e9363",
38
+ "@agoric/orchestration": "0.1.1-dev-a2e9363.0+a2e9363",
39
+ "@agoric/store": "0.9.3-dev-a2e9363.0+a2e9363",
40
+ "@agoric/vat-data": "0.5.3-dev-a2e9363.0+a2e9363",
41
+ "@agoric/vow": "0.1.1-dev-a2e9363.0+a2e9363",
42
+ "@agoric/zoe": "0.26.3-dev-a2e9363.0+a2e9363",
43
43
  "@cosmjs/proto-signing": "^0.32.4",
44
44
  "@cosmjs/stargate": "^0.32.4",
45
45
  "@endo/base64": "^1.0.9",
@@ -78,5 +78,5 @@
78
78
  "publishConfig": {
79
79
  "access": "public"
80
80
  },
81
- "gitHead": "8657c4cfc5dcb48602f730574afe5efb6f8ffb24"
81
+ "gitHead": "a2e936366843f74f9d101f3db4b1e76858abe3d7"
82
82
  }
@@ -0,0 +1,32 @@
1
+ import { boardSlottingMarshaller } from '@agoric/client-utils';
2
+
3
+ /**
4
+ * @import {BridgeAction} from '@agoric/smart-wallet/src/smartWallet.js';
5
+ */
6
+
7
+ const marshaller = boardSlottingMarshaller();
8
+
9
+ /**
10
+ * @param {BridgeAction} bridgeAction
11
+ * @param {Pick<import('stream').Writable,'write'>} stdout
12
+ */
13
+ const outputAction = (bridgeAction, stdout) => {
14
+ const capData = marshaller.toCapData(harden(bridgeAction));
15
+ stdout.write(JSON.stringify(capData));
16
+ stdout.write('\n');
17
+ };
18
+
19
+ export const sendHint =
20
+ 'Now use `agoric wallet send ...` to sign and broadcast the offer.\n';
21
+
22
+ /**
23
+ * @param {BridgeAction} bridgeAction
24
+ * @param {{
25
+ * stdout: Pick<import('stream').Writable,'write'>,
26
+ * stderr: Pick<import('stream').Writable,'write'>,
27
+ * }} io
28
+ */
29
+ export const outputActionAndHint = (bridgeAction, { stdout, stderr }) => {
30
+ outputAction(bridgeAction, stdout);
31
+ stderr.write(sendHint);
32
+ };
package/src/cli/cli.js CHANGED
@@ -12,7 +12,9 @@ import {
12
12
  readFile as readAsync,
13
13
  writeFile as writeAsync,
14
14
  } from 'node:fs/promises';
15
- import configLib from './config.js';
15
+ import { addConfigCommands } from './config-commands.js';
16
+ import { addOperatorCommands } from './operator-commands.js';
17
+ import * as configLib from './config.js';
16
18
  import transferLib from './transfer.js';
17
19
  import { makeFile } from '../util/file.js';
18
20
 
@@ -45,108 +47,16 @@ export const initProgram = (
45
47
  `${defaultHome}/.fast-usdc/`,
46
48
  );
47
49
 
48
- const config = program.command('config').description('Manage config');
49
-
50
- const configFilename = 'config.json';
51
- const getConfigPath = () => {
52
- const { home: configDir } = program.opts();
53
- return configDir + configFilename;
50
+ const makeConfigFile = () => {
51
+ const getConfigPath = () => {
52
+ const { home: configDir } = program.opts();
53
+ return `${configDir}config.json`;
54
+ };
55
+ return makeFile(getConfigPath(), readFile, writeFile, mkdir, exists);
54
56
  };
55
57
 
56
- const makeConfigFile = () =>
57
- makeFile(getConfigPath(), readFile, writeFile, mkdir, exists);
58
-
59
- config
60
- .command('show')
61
- .description('Show current config')
62
- .action(async () => {
63
- await configHelpers.show(makeConfigFile());
64
- });
65
-
66
- config
67
- .command('init')
68
- .description('Set initial config values')
69
- .requiredOption(
70
- '--noble-seed <seed>',
71
- 'Seed phrase for Noble account. CAUTION: Stored unencrypted in file system',
72
- )
73
- .requiredOption(
74
- '--eth-seed <seed>',
75
- 'Seed phrase for Ethereum account. CAUTION: Stored unencrypted in file system',
76
- )
77
- .requiredOption(
78
- '--agoric-seed <seed>',
79
- 'Seed phrase for Agoric LP account. CAUTION: Stored unencrypted in file system',
80
- )
81
- .option(
82
- '--agoric-rpc [url]',
83
- 'Agoric RPC endpoint',
84
- 'http://127.0.0.1:26656',
85
- )
86
- .option(
87
- '--agoric-api [url]',
88
- 'Agoric RPC endpoint',
89
- 'http://127.0.0.1:1317',
90
- )
91
- .option('--noble-rpc [url]', 'Noble RPC endpoint', 'http://127.0.0.1:26657')
92
- .option('--noble-api [url]', 'Noble API endpoint', 'http://127.0.0.1:1318')
93
- .option('--eth-rpc [url]', 'Ethereum RPC Endpoint', 'http://127.0.0.1:8545')
94
- .option(
95
- '--noble-to-agoric-channel [channel]',
96
- 'Channel ID on Noble for Agoric',
97
- 'channel-21',
98
- )
99
- .option(
100
- '--token-messenger-address [address]',
101
- 'Address of TokenMessenger contract',
102
- // Default to ETH mainnet contract address. For ETH sepolia, use 0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5
103
- '0xbd3fa81b58ba92a82136038b25adec7066af3155',
104
- )
105
- .option(
106
- '--token-contract-address [address]',
107
- 'Address of USDC token contract',
108
- // Detault to ETH mainnet token address. For ETH sepolia, use 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238
109
- '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
110
- )
111
- .action(async options => {
112
- await configHelpers.init(makeConfigFile(), options);
113
- });
114
-
115
- config
116
- .command('update')
117
- .description('Update config values')
118
- .option(
119
- '--noble-seed [string]',
120
- 'Seed phrase for Noble account. CAUTION: Stored unencrypted in file system',
121
- )
122
- .option(
123
- '--eth-seed [string]',
124
- 'Seed phrase for Ethereum account. CAUTION: Stored unencrypted in file system',
125
- )
126
- .option(
127
- '--agoric-seed <seed>',
128
- 'Seed phrase for Agoric LP account. CAUTION: Stored unencrypted in file system',
129
- )
130
- .option('--agoric-rpc [url]', 'Agoric RPC endpoint')
131
- .option('--agoric-api [url]', 'Agoric API endpoint')
132
- .option('--noble-rpc [url]', 'Noble RPC endpoint')
133
- .option('--noble-api [url]', 'Noble API endpoint')
134
- .option('--eth-rpc [url]', 'Ethereum RPC Endpoint')
135
- .option(
136
- '--noble-to-agoric-channel [channel]',
137
- 'Channel ID on Noble for Agoric',
138
- )
139
- .option(
140
- '--token-messenger-address [address]',
141
- 'Address of TokenMessenger contract',
142
- )
143
- .option(
144
- '--token-contract-address [address]',
145
- 'Address of USDC token contract',
146
- )
147
- .action(async options => {
148
- await configHelpers.update(makeConfigFile(), options);
149
- });
58
+ addConfigCommands(program, configHelpers, makeConfigFile);
59
+ addOperatorCommands(program);
150
60
 
151
61
  /** @param {string} value */
152
62
  const parseDecimal = value => {
@@ -0,0 +1,108 @@
1
+ /**
2
+ * @import {Command} from 'commander';
3
+ * @import {File} from '../util/file.js';
4
+ * @import * as ConfigHelpers from './config.js';
5
+ */
6
+ /**
7
+ *
8
+ * @param {Command} program
9
+ * @param {ConfigHelpers} configHelpers
10
+ * @param {() => File} makeConfigFile
11
+ */
12
+ export const addConfigCommands = (program, configHelpers, makeConfigFile) => {
13
+ const config = program.command('config').description('Manage config');
14
+
15
+ config
16
+ .command('show')
17
+ .description('Show current config')
18
+ .action(async () => {
19
+ await configHelpers.show(makeConfigFile());
20
+ });
21
+
22
+ config
23
+ .command('init')
24
+ .description('Set initial config values')
25
+ .requiredOption(
26
+ '--noble-seed <seed>',
27
+ 'Seed phrase for Noble account. CAUTION: Stored unencrypted in file system',
28
+ )
29
+ .requiredOption(
30
+ '--eth-seed <seed>',
31
+ 'Seed phrase for Ethereum account. CAUTION: Stored unencrypted in file system',
32
+ )
33
+ .requiredOption(
34
+ '--agoric-seed <seed>',
35
+ 'Seed phrase for Agoric LP account. CAUTION: Stored unencrypted in file system',
36
+ )
37
+ .option(
38
+ '--agoric-rpc [url]',
39
+ 'Agoric RPC endpoint',
40
+ 'http://127.0.0.1:26656',
41
+ )
42
+ .option(
43
+ '--agoric-api [url]',
44
+ 'Agoric RPC endpoint',
45
+ 'http://127.0.0.1:1317',
46
+ )
47
+ .option('--noble-rpc [url]', 'Noble RPC endpoint', 'http://127.0.0.1:26657')
48
+ .option('--noble-api [url]', 'Noble API endpoint', 'http://127.0.0.1:1318')
49
+ .option('--eth-rpc [url]', 'Ethereum RPC Endpoint', 'http://127.0.0.1:8545')
50
+ .option(
51
+ '--noble-to-agoric-channel [channel]',
52
+ 'Channel ID on Noble for Agoric',
53
+ 'channel-21',
54
+ )
55
+ .option(
56
+ '--token-messenger-address [address]',
57
+ 'Address of TokenMessenger contract',
58
+ // Default to ETH mainnet contract address. For ETH sepolia, use 0x9f3B8679c73C2Fef8b59B4f3444d4e156fb70AA5
59
+ '0xbd3fa81b58ba92a82136038b25adec7066af3155',
60
+ )
61
+ .option(
62
+ '--token-contract-address [address]',
63
+ 'Address of USDC token contract',
64
+ // Detault to ETH mainnet token address. For ETH sepolia, use 0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238
65
+ '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
66
+ )
67
+ .action(async options => {
68
+ await configHelpers.init(makeConfigFile(), options);
69
+ });
70
+
71
+ config
72
+ .command('update')
73
+ .description('Update config values')
74
+ .option(
75
+ '--noble-seed [string]',
76
+ 'Seed phrase for Noble account. CAUTION: Stored unencrypted in file system',
77
+ )
78
+ .option(
79
+ '--eth-seed [string]',
80
+ 'Seed phrase for Ethereum account. CAUTION: Stored unencrypted in file system',
81
+ )
82
+ .option(
83
+ '--agoric-seed <seed>',
84
+ 'Seed phrase for Agoric LP account. CAUTION: Stored unencrypted in file system',
85
+ )
86
+ .option('--agoric-rpc [url]', 'Agoric RPC endpoint')
87
+ .option('--agoric-api [url]', 'Agoric API endpoint')
88
+ .option('--noble-rpc [url]', 'Noble RPC endpoint')
89
+ .option('--noble-api [url]', 'Noble API endpoint')
90
+ .option('--eth-rpc [url]', 'Ethereum RPC Endpoint')
91
+ .option(
92
+ '--noble-to-agoric-channel [channel]',
93
+ 'Channel ID on Noble for Agoric',
94
+ )
95
+ .option(
96
+ '--token-messenger-address [address]',
97
+ 'Address of TokenMessenger contract',
98
+ )
99
+ .option(
100
+ '--token-contract-address [address]',
101
+ 'Address of USDC token contract',
102
+ )
103
+ .action(async options => {
104
+ await configHelpers.update(makeConfigFile(), options);
105
+ });
106
+
107
+ return config;
108
+ };
package/src/cli/config.js CHANGED
@@ -15,10 +15,10 @@ import { stdin as input, stdout as output } from 'node:process';
15
15
  }} ConfigOpts
16
16
  */
17
17
 
18
- /** @import { file } from '../util/file' */
18
+ /** @import { File } from '../util/file' */
19
19
 
20
- const init = async (
21
- /** @type {file} */ configFile,
20
+ export const init = async (
21
+ /** @type {File} */ configFile,
22
22
  /** @type {ConfigOpts} */ options,
23
23
  out = console,
24
24
  rl = readline.createInterface({ input, output }),
@@ -52,8 +52,8 @@ const init = async (
52
52
  await writeConfig();
53
53
  };
54
54
 
55
- const update = async (
56
- /** @type {file} */ configFile,
55
+ export const update = async (
56
+ /** @type {File} */ configFile,
57
57
  /** @type {Partial<ConfigOpts>} */ options,
58
58
  out = console,
59
59
  ) => {
@@ -83,7 +83,7 @@ const update = async (
83
83
  await updateConfig({ ...JSON.parse(file), ...options });
84
84
  };
85
85
 
86
- const show = async (/** @type {file} */ configFile, out = console) => {
86
+ export const show = async (/** @type {File} */ configFile, out = console) => {
87
87
  let contents;
88
88
  await null;
89
89
  try {
@@ -97,5 +97,3 @@ const show = async (/** @type {file} */ configFile, out = console) => {
97
97
  out.log(`Config found at ${configFile.path}:`);
98
98
  out.log(contents);
99
99
  };
100
-
101
- export default { init, update, show };
@@ -0,0 +1,78 @@
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
+ */
7
+
8
+ import { fetchEnvNetworkConfig, makeVstorageKit } from '@agoric/client-utils';
9
+ import { INVITATION_MAKERS_DESC } from '../exos/transaction-feed.js';
10
+ import { outputActionAndHint } from './bridge-action.js';
11
+
12
+ /**
13
+ * @param {Command} program
14
+ */
15
+ export const addOperatorCommands = program => {
16
+ const operator = program
17
+ .command('operator')
18
+ .description('Oracle operator commands');
19
+
20
+ operator
21
+ .command('accept')
22
+ .description('Accept invitation to be an operator')
23
+ .addHelpText(
24
+ 'after',
25
+ '\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
+ )
27
+ .option(
28
+ '--offerId <string>',
29
+ 'Offer id',
30
+ String,
31
+ `operatorAccept-${Date.now()}`,
32
+ )
33
+ .action(async opts => {
34
+ const networkConfig = await fetchEnvNetworkConfig({
35
+ env: process.env,
36
+ fetch,
37
+ });
38
+ const vsk = await makeVstorageKit({ fetch }, networkConfig);
39
+ const instance = vsk.agoricNames.instance.fastUsdc;
40
+ assert(instance, 'fastUsdc instance not in agoricNames');
41
+
42
+ /** @type {OfferSpec} */
43
+ const offer = {
44
+ id: opts.offerId,
45
+ invitationSpec: {
46
+ source: 'purse',
47
+ instance,
48
+ description: INVITATION_MAKERS_DESC,
49
+ },
50
+ proposal: {},
51
+ };
52
+
53
+ /** @type {ExecuteOfferAction} */
54
+ const bridgeAction = {
55
+ method: 'executeOffer',
56
+ offer,
57
+ };
58
+
59
+ outputActionAndHint(bridgeAction, {
60
+ stderr: process.stderr,
61
+ stdout: process.stdout,
62
+ });
63
+ });
64
+
65
+ operator
66
+ .command('attest')
67
+ .description('Attest to an observed Fast USDC transfer')
68
+ .requiredOption('--previousOfferId <string>', 'Offer id', String)
69
+ .action(async options => {
70
+ const { previousOfferId } = options;
71
+ console.error(
72
+ 'TODO: Implement attest logic for request:',
73
+ previousOfferId,
74
+ );
75
+ });
76
+
77
+ return operator;
78
+ };
@@ -9,13 +9,13 @@ import {
9
9
  } from '../util/noble.js';
10
10
  import { queryFastUSDCLocalChainAccount } from '../util/agoric.js';
11
11
 
12
- /** @import { file } from '../util/file' */
12
+ /** @import { File } from '../util/file' */
13
13
  /** @import { VStorage } from '@agoric/client-utils' */
14
14
  /** @import { SigningStargateClient } from '@cosmjs/stargate' */
15
15
  /** @import { JsonRpcProvider as ethProvider } from 'ethers' */
16
16
 
17
17
  const transfer = async (
18
- /** @type {file} */ configFile,
18
+ /** @type {File} */ configFile,
19
19
  /** @type {string} */ amount,
20
20
  /** @type {string} */ destination,
21
21
  out = console,
package/src/util/file.js CHANGED
@@ -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 */