@reserve-protocol/dtf-cli 0.1.0 → 0.1.2

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 (97) hide show
  1. package/dist/index.js +29298 -144
  2. package/package.json +3 -3
  3. package/dist/commands/basket.d.ts +0 -3
  4. package/dist/commands/basket.d.ts.map +0 -1
  5. package/dist/commands/basket.js +0 -131
  6. package/dist/commands/basket.js.map +0 -1
  7. package/dist/commands/deploy.d.ts +0 -3
  8. package/dist/commands/deploy.d.ts.map +0 -1
  9. package/dist/commands/deploy.js +0 -495
  10. package/dist/commands/deploy.js.map +0 -1
  11. package/dist/commands/discover.d.ts +0 -3
  12. package/dist/commands/discover.d.ts.map +0 -1
  13. package/dist/commands/discover.js +0 -141
  14. package/dist/commands/discover.js.map +0 -1
  15. package/dist/commands/earn.d.ts +0 -3
  16. package/dist/commands/earn.d.ts.map +0 -1
  17. package/dist/commands/earn.js +0 -42
  18. package/dist/commands/earn.js.map +0 -1
  19. package/dist/commands/fees.d.ts +0 -3
  20. package/dist/commands/fees.d.ts.map +0 -1
  21. package/dist/commands/fees.js +0 -82
  22. package/dist/commands/fees.js.map +0 -1
  23. package/dist/commands/forum.d.ts +0 -3
  24. package/dist/commands/forum.d.ts.map +0 -1
  25. package/dist/commands/forum.js +0 -304
  26. package/dist/commands/forum.js.map +0 -1
  27. package/dist/commands/governance.d.ts +0 -3
  28. package/dist/commands/governance.d.ts.map +0 -1
  29. package/dist/commands/governance.js +0 -97
  30. package/dist/commands/governance.js.map +0 -1
  31. package/dist/commands/info.d.ts +0 -3
  32. package/dist/commands/info.d.ts.map +0 -1
  33. package/dist/commands/info.js +0 -114
  34. package/dist/commands/info.js.map +0 -1
  35. package/dist/commands/prices.d.ts +0 -3
  36. package/dist/commands/prices.d.ts.map +0 -1
  37. package/dist/commands/prices.js +0 -71
  38. package/dist/commands/prices.js.map +0 -1
  39. package/dist/commands/proposals.d.ts +0 -3
  40. package/dist/commands/proposals.d.ts.map +0 -1
  41. package/dist/commands/proposals.js +0 -261
  42. package/dist/commands/proposals.js.map +0 -1
  43. package/dist/commands/quote.d.ts +0 -3
  44. package/dist/commands/quote.d.ts.map +0 -1
  45. package/dist/commands/quote.js +0 -100
  46. package/dist/commands/quote.js.map +0 -1
  47. package/dist/commands/rebalance-history.d.ts +0 -24
  48. package/dist/commands/rebalance-history.d.ts.map +0 -1
  49. package/dist/commands/rebalance-history.js +0 -229
  50. package/dist/commands/rebalance-history.js.map +0 -1
  51. package/dist/commands/rebalance.d.ts +0 -3
  52. package/dist/commands/rebalance.d.ts.map +0 -1
  53. package/dist/commands/rebalance.js +0 -162
  54. package/dist/commands/rebalance.js.map +0 -1
  55. package/dist/commands/revenue.d.ts +0 -3
  56. package/dist/commands/revenue.d.ts.map +0 -1
  57. package/dist/commands/revenue.js +0 -135
  58. package/dist/commands/revenue.js.map +0 -1
  59. package/dist/commands/roles.d.ts +0 -3
  60. package/dist/commands/roles.d.ts.map +0 -1
  61. package/dist/commands/roles.js +0 -53
  62. package/dist/commands/roles.js.map +0 -1
  63. package/dist/commands/rsr-burns.d.ts +0 -3
  64. package/dist/commands/rsr-burns.d.ts.map +0 -1
  65. package/dist/commands/rsr-burns.js +0 -134
  66. package/dist/commands/rsr-burns.js.map +0 -1
  67. package/dist/commands/staking.d.ts +0 -3
  68. package/dist/commands/staking.d.ts.map +0 -1
  69. package/dist/commands/staking.js +0 -102
  70. package/dist/commands/staking.js.map +0 -1
  71. package/dist/index.d.ts +0 -3
  72. package/dist/index.d.ts.map +0 -1
  73. package/dist/index.js.map +0 -1
  74. package/dist/lib/cache.d.ts +0 -4
  75. package/dist/lib/cache.d.ts.map +0 -1
  76. package/dist/lib/cache.js +0 -58
  77. package/dist/lib/cache.js.map +0 -1
  78. package/dist/lib/cached-config.d.ts +0 -12
  79. package/dist/lib/cached-config.d.ts.map +0 -1
  80. package/dist/lib/cached-config.js +0 -18
  81. package/dist/lib/cached-config.js.map +0 -1
  82. package/dist/lib/config.d.ts +0 -22
  83. package/dist/lib/config.d.ts.map +0 -1
  84. package/dist/lib/config.js +0 -94
  85. package/dist/lib/config.js.map +0 -1
  86. package/dist/lib/dtf-registry.d.ts +0 -19
  87. package/dist/lib/dtf-registry.d.ts.map +0 -1
  88. package/dist/lib/dtf-registry.js +0 -54
  89. package/dist/lib/dtf-registry.js.map +0 -1
  90. package/dist/lib/output.d.ts +0 -16
  91. package/dist/lib/output.d.ts.map +0 -1
  92. package/dist/lib/output.js +0 -73
  93. package/dist/lib/output.js.map +0 -1
  94. package/dist/lib/token-symbols.d.ts +0 -7
  95. package/dist/lib/token-symbols.d.ts.map +0 -1
  96. package/dist/lib/token-symbols.js +0 -44
  97. package/dist/lib/token-symbols.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reserve-protocol/dtf-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -8,11 +8,11 @@
8
8
  },
9
9
  "files": ["dist"],
10
10
  "scripts": {
11
- "build": "tsc -p tsconfig.build.json",
11
+ "build": "bun build src/index.ts --outfile dist/index.js --target node",
12
12
  "prepublishOnly": "bun run build"
13
13
  },
14
14
  "dependencies": {
15
- "@reserve-protocol/dtf-sdk": "^0.1.0",
15
+ "@reserve-protocol/dtf-sdk": "workspace:*",
16
16
  "viem": "^2.45.2"
17
17
  }
18
18
  }
@@ -1,3 +0,0 @@
1
- import type { CliConfig } from '../lib/config';
2
- export declare function basketCommand(address: string, config: CliConfig): Promise<void>;
3
- //# sourceMappingURL=basket.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"basket.d.ts","sourceRoot":"","sources":["../../src/commands/basket.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAY9C,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,iBAUrE"}
@@ -1,131 +0,0 @@
1
- import { formatUnits } from 'viem';
2
- import { createDtfClients, readBasket, fetchDtfBasket, fetchDtfConfig, fetchTokenPrices, } from '@reserve-protocol/dtf-sdk';
3
- import { fetchDtfConfigCached } from '../lib/cached-config';
4
- import { printHeader, printJson, printTable, formatAddress, formatUsd, formatPct, chainLabel, } from '../lib/output';
5
- export async function basketCommand(address, config) {
6
- // WHY: Use the API path by default — one call for basket + prices + weights.
7
- // Falls back to RPC path if API fails (e.g., new DTF not yet indexed).
8
- try {
9
- await basketFromApi(address, config);
10
- }
11
- catch {
12
- // NOTE: API may fail for newly deployed DTFs not yet indexed.
13
- console.warn('API basket fetch failed, falling back to RPC...');
14
- await basketFromRpc(address, config);
15
- }
16
- }
17
- async function basketFromApi(address, config) {
18
- const { publicClient } = createDtfClients({
19
- chainId: config.chainId,
20
- rpc: config.rpc,
21
- });
22
- const [data, dtfConfig] = await Promise.all([
23
- fetchDtfBasket(config.chainId, address),
24
- fetchDtfConfigCached(fetchDtfConfig, publicClient, config.chainId, address),
25
- ]);
26
- // WHY: API doesn't always return token symbols (e.g. vault tokens like mooMorpho).
27
- // Subgraph config always has them, so use it as fallback.
28
- const symbolLookup = {};
29
- for (const t of dtfConfig.tokens) {
30
- symbolLookup[t.address.toLowerCase()] = t.symbol;
31
- }
32
- if (config.json) {
33
- printJson({
34
- dtf: address,
35
- chain: config.chainId,
36
- chainLabel: chainLabel(config.chainId),
37
- tokens: data.basket.map((t) => ({
38
- address: t.address,
39
- symbol: t.symbol ?? symbolLookup[t.address.toLowerCase()] ?? null,
40
- decimals: t.decimals,
41
- price: t.price,
42
- weight: Number(t.weight) / 100,
43
- amount: t.amount,
44
- amountRaw: t.amountRaw,
45
- value: t.price * t.amount,
46
- })),
47
- totalSupply: data.totalSupply,
48
- tvl: Math.round(data.price * data.totalSupply),
49
- sharePrice: data.price,
50
- marketCap: data.marketCap,
51
- });
52
- return;
53
- }
54
- printHeader(`DTF Basket — ${formatAddress(address)} (Chain ${config.chainId})`);
55
- console.log();
56
- printTable([
57
- { header: 'Address', key: 'address' },
58
- { header: 'Weight', key: 'weight', align: 'right' },
59
- { header: 'Price', key: 'price', align: 'right' },
60
- { header: 'Amount/Share', key: 'amount', align: 'right' },
61
- ], data.basket.map((t) => ({
62
- address: formatAddress(t.address),
63
- weight: `${t.weight}%`,
64
- price: formatUsd(t.price),
65
- amount: t.amount.toLocaleString('en-US', { maximumFractionDigits: 6 }),
66
- })));
67
- console.log();
68
- console.log(`Share Price: ${formatUsd(data.price)}`);
69
- console.log(`Market Cap: ${formatUsd(data.marketCap)}`);
70
- }
71
- async function basketFromRpc(address, config) {
72
- const { publicClient } = createDtfClients({
73
- chainId: config.chainId,
74
- rpc: config.rpc,
75
- });
76
- const basket = await readBasket(publicClient, address);
77
- const prices = await fetchTokenPrices(config.chainId, basket.tokens.map((t) => t.address));
78
- const tokenValues = basket.tokens.map((token, i) => {
79
- const balance = basket.balances[i];
80
- const balanceFormatted = Number(formatUnits(balance, token.decimals));
81
- const price = prices[token.address.toLowerCase()] ?? 0;
82
- const usdValue = balanceFormatted * price;
83
- return { token, balance, balanceFormatted, price, usdValue };
84
- });
85
- const tvl = tokenValues.reduce((sum, t) => sum + t.usdValue, 0);
86
- const totalSupplyFormatted = Number(formatUnits(basket.totalSupply, 18));
87
- if (config.json) {
88
- printJson({
89
- dtf: address,
90
- chain: config.chainId,
91
- chainLabel: chainLabel(config.chainId),
92
- tokens: tokenValues.map((t) => ({
93
- symbol: t.token.symbol,
94
- address: t.token.address,
95
- balance: t.balance.toString(),
96
- decimals: t.token.decimals,
97
- price: t.price,
98
- weight: tvl > 0 ? t.usdValue / tvl : 0,
99
- usdValue: Math.round(t.usdValue),
100
- })),
101
- totalSupply: basket.totalSupply.toString(),
102
- tvl: Math.round(tvl),
103
- sharePrice: totalSupplyFormatted > 0 ? tvl / totalSupplyFormatted : 0,
104
- });
105
- return;
106
- }
107
- printHeader(`DTF Basket — ${formatAddress(address)} (Chain ${config.chainId})`);
108
- console.log();
109
- printTable([
110
- { header: 'Token', key: 'symbol' },
111
- { header: 'Address', key: 'address' },
112
- { header: 'Balance', key: 'balance', align: 'right' },
113
- { header: 'Weight', key: 'weight', align: 'right' },
114
- { header: 'Value (USD)', key: 'value', align: 'right' },
115
- ], tokenValues.map((t) => ({
116
- symbol: t.token.symbol,
117
- address: formatAddress(t.token.address),
118
- balance: t.balanceFormatted.toLocaleString('en-US', {
119
- maximumFractionDigits: 4,
120
- }),
121
- weight: tvl > 0 ? formatPct(t.usdValue / tvl) : '—',
122
- value: formatUsd(t.usdValue),
123
- })));
124
- console.log();
125
- console.log(`TVL: ${formatUsd(tvl)}`);
126
- console.log(`Total Supply: ${totalSupplyFormatted.toLocaleString('en-US', { maximumFractionDigits: 2 })}`);
127
- if (totalSupplyFormatted > 0) {
128
- console.log(`Share Price: ${formatUsd(tvl / totalSupplyFormatted)}`);
129
- }
130
- }
131
- //# sourceMappingURL=basket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"basket.js","sourceRoot":"","sources":["../../src/commands/basket.ts"],"names":[],"mappings":"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"}
@@ -1,3 +0,0 @@
1
- import type { CliConfig } from '../lib/config';
2
- export declare function deployCommand(config: CliConfig, args: string[]): Promise<void>;
3
- //# sourceMappingURL=deploy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AA8D9C,wBAAsB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,iBAsMpE"}
@@ -1,495 +0,0 @@
1
- import { readFileSync, existsSync } from 'fs';
2
- import { isAddress } from 'viem';
3
- import { createDtfClients, submitZapDeploy, resolveToken, getTokenRegistry, fetchTokenPrices, fetchTokenMetadata, extractDeployedAddress, buildDefaultFeeRecipients, VOTE_LOCK_ADDRESS, DEFAULT_TVL_FEE, DEFAULT_MINT_FEE, DEFAULT_AUCTION_LENGTH, DEFAULT_FLAGS, DEFAULT_TRADING_GOV_PARAMS, DEFAULT_OWNER_GOV_PARAMS, DEFAULT_GUARDIANS, DEFAULT_AUCTION_LAUNCHERS, DEFAULT_DEPLOY_SLIPPAGE, } from '@reserve-protocol/dtf-sdk';
4
- import { printJson, printHeader, printTable, chainLabel } from '../lib/output';
5
- // ETH sentinel address used by Zapper API for native ETH
6
- const ETH_SENTINEL = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE';
7
- const CHAIN_SLUGS = {
8
- 1: 'ethereum',
9
- 56: 'bsc',
10
- 8453: 'base',
11
- };
12
- const DEPLOY_HELP = `
13
- dtf deploy — Deploy a new DTF
14
-
15
- Usage:
16
- dtf deploy --name "My Index" --symbol MIDX --basket "50% WETH, 30% USDC, 20% cbBTC" --amount 0.1 --wallet-key $KEY
17
- dtf deploy --config deploy.json --wallet-key $KEY
18
- dtf deploy --list-tokens --chain 8453
19
- dtf deploy --name "My DTF" --symbol MDTF --basket basket.csv --amount 0.1 --wallet-key $KEY
20
- dtf deploy --name "Test" --symbol TST --basket "50% WETH, 50% USDC" --wallet-key $KEY --dry-run
21
-
22
- Options:
23
- --name <name> DTF name
24
- --symbol <symbol> DTF ticker symbol
25
- --basket <spec> Basket: inline "50% WETH, 30% USDC" or path to .csv file
26
- --amount <eth> Amount of ETH to deposit
27
- --mandate <text> DTF mandate/description (optional)
28
- --config <file> JSON config file (alternative to --name/--symbol/--basket)
29
- --ungoverned Deploy without DAO governance (wallet-owned)
30
- --dry-run Preview without sending transaction
31
- --list-tokens Show available token symbols for --chain
32
- --wallet-key <key> Private key (or WALLET_KEY env var)
33
- --json JSON output
34
-
35
- Tip: Use WALLET_KEY env var instead of --wallet-key to keep your key out of shell history.
36
- `;
37
- // -- Main --
38
- export async function deployCommand(config, args) {
39
- if (args.includes('--help')) {
40
- console.log(DEPLOY_HELP);
41
- return;
42
- }
43
- if (args.includes('--list-tokens')) {
44
- return listTokens(config);
45
- }
46
- // -- Parse & validate --
47
- const deployConfig = parseDeployConfig(args);
48
- const chainId = config.chainId;
49
- const ungoverned = deployConfig.ungoverned;
50
- const dryRun = args.includes('--dry-run');
51
- if (!config.walletKey) {
52
- throw new Error('Deploy requires --wallet-key or WALLET_KEY env var');
53
- }
54
- if (!ungoverned) {
55
- const voteLock = VOTE_LOCK_ADDRESS[chainId];
56
- if (!voteLock || voteLock === '0x0000000000000000000000000000000000000000') {
57
- throw new Error(`Governed deploy not available on ${chainLabel(chainId)} (no vote-lock DAO). Use --ungoverned or deploy on Base.`);
58
- }
59
- }
60
- validateBasket(deployConfig.basket);
61
- // -- Resolve addresses & fetch prices --
62
- const resolvedBasket = resolveBasketAddresses(deployConfig.basket, chainId);
63
- const { publicClient, walletClient, account } = createDtfClients({
64
- chainId,
65
- rpc: config.rpc,
66
- walletKey: config.walletKey,
67
- });
68
- if (!walletClient || !account) {
69
- throw new Error('Failed to create wallet client from provided key');
70
- }
71
- const addresses = resolvedBasket.map((t) => t.address);
72
- const needDecimals = resolvedBasket.filter((t) => t.decimals === undefined);
73
- // WHY: Price and metadata fetches are independent — run in parallel.
74
- const [prices, metaEntries] = await Promise.all([
75
- fetchTokenPrices(chainId, addresses),
76
- needDecimals.length > 0
77
- // WHY: createDtfClients returns a narrower type than fetchTokenMetadata expects.
78
- // The PublicClient from viem satisfies the multicall interface at runtime.
79
- ? fetchTokenMetadata(publicClient, needDecimals.map((t) => t.address))
80
- : Promise.resolve([]),
81
- ]);
82
- const decimalMap = {};
83
- for (const m of metaEntries) {
84
- decimalMap[m.address.toLowerCase()] = m.decimals;
85
- }
86
- // -- Calculate basket amounts --
87
- const { basketAssets, basketAmounts } = calculateBasketAmounts(resolvedBasket, prices, decimalMap, chainId);
88
- // -- Build Zap params --
89
- const stToken = ungoverned ? undefined : VOTE_LOCK_ADDRESS[chainId];
90
- const amountInWei = parseEthToWei(deployConfig.amount);
91
- const feeRecipients = stToken
92
- ? buildDefaultFeeRecipients(chainId, stToken)
93
- : [{ recipient: account.address, portion: (10n ** 18n).toString() }];
94
- const zapParams = {
95
- chainId,
96
- tokenIn: ETH_SENTINEL,
97
- amountIn: amountInWei.toString(),
98
- signer: account.address,
99
- slippage: DEFAULT_DEPLOY_SLIPPAGE,
100
- basicDetails: {
101
- assets: basketAssets,
102
- amounts: basketAmounts,
103
- name: deployConfig.name,
104
- symbol: deployConfig.symbol,
105
- },
106
- additionalDetails: {
107
- auctionLength: DEFAULT_AUCTION_LENGTH.toString(),
108
- feeRecipients,
109
- tvlFee: DEFAULT_TVL_FEE.toString(),
110
- mintFee: DEFAULT_MINT_FEE.toString(),
111
- mandate: deployConfig.mandate,
112
- },
113
- folioFlags: { ...DEFAULT_FLAGS },
114
- stToken,
115
- ownerGovParams: stToken
116
- ? { ...DEFAULT_OWNER_GOV_PARAMS, guardians: DEFAULT_GUARDIANS[chainId] ?? [] }
117
- : undefined,
118
- tradingGovParams: stToken
119
- ? { ...DEFAULT_TRADING_GOV_PARAMS, guardians: DEFAULT_GUARDIANS[chainId] ?? [] }
120
- : undefined,
121
- auctionLaunchers: DEFAULT_AUCTION_LAUNCHERS[chainId] ?? [],
122
- basketManagers: [],
123
- brandManagers: [],
124
- };
125
- // -- Dry run --
126
- if (dryRun) {
127
- return outputDryRun(config, deployConfig, chainId, ungoverned, resolvedBasket, basketAmounts, prices, zapParams);
128
- }
129
- // -- Deploy --
130
- if (!config.json) {
131
- process.stdout.write(`Deploying ${deployConfig.name} (${deployConfig.symbol}) on ${chainLabel(chainId)} with ${deployConfig.amount} ETH...\n\n`);
132
- }
133
- const zapResult = await submitZapDeploy(zapParams);
134
- if (zapResult.insufficientFunds) {
135
- throw new Error(`Insufficient ETH balance. Need ${deployConfig.amount} ETH.`);
136
- }
137
- if (!zapResult.tx) {
138
- throw new Error('Zapper API returned no transaction data. Check basket tokens and amounts.');
139
- }
140
- if (zapResult.approvalNeeded) {
141
- // WHY: Should never happen with native ETH. If it does, something is wrong.
142
- throw new Error('Unexpected: Zapper requires token approval for native ETH.');
143
- }
144
- if (!config.json) {
145
- process.stdout.write(' Sending deploy tx... ');
146
- }
147
- const deployHash = await walletClient.sendTransaction({
148
- to: zapResult.tx.to,
149
- data: zapResult.tx.data,
150
- value: BigInt(zapResult.tx.value),
151
- chain: null,
152
- });
153
- // WHY: Print hash immediately so user has it even if they Ctrl+C during confirmation wait.
154
- // In JSON mode, print to stderr so it doesn't corrupt JSON output on stdout.
155
- if (config.json) {
156
- console.error(`tx: ${deployHash}`);
157
- }
158
- else {
159
- process.stdout.write(`done (${deployHash.slice(0, 10)}...${deployHash.slice(-4)})\n`);
160
- process.stdout.write(' Waiting for confirmation... ');
161
- }
162
- const receipt = await publicClient.waitForTransactionReceipt({
163
- hash: deployHash,
164
- timeout: 300_000, // 5 min
165
- });
166
- if (receipt.status === 'reverted') {
167
- const explorer = chainId === 1 ? 'etherscan.io' : chainId === 8453 ? 'basescan.org' : 'bscscan.com';
168
- throw new Error(`Deploy transaction reverted. Hash: ${deployHash}\nCheck: https://${explorer}/tx/${deployHash}`);
169
- }
170
- if (!config.json) {
171
- process.stdout.write('done\n');
172
- }
173
- // WHY: viem's receipt.logs type is slightly wider than Log[].
174
- // extractDeployedAddress only needs topics + data which are always present.
175
- const deployedAddress = extractDeployedAddress(receipt.logs);
176
- const registerUrl = `https://app.reserve.org/${CHAIN_SLUGS[chainId]}/index-dtf/${deployedAddress}/overview`;
177
- if (config.json) {
178
- printJson({
179
- deployed: true,
180
- dtf: deployedAddress,
181
- name: deployConfig.name,
182
- symbol: deployConfig.symbol,
183
- chain: chainId,
184
- chainLabel: chainLabel(chainId),
185
- mode: ungoverned ? 'ungoverned' : 'governed',
186
- amountEth: deployConfig.amount.toString(),
187
- sharesOut: zapResult.amountOut,
188
- priceImpact: zapResult.priceImpact,
189
- gas: zapResult.gas,
190
- txHash: deployHash,
191
- registerUrl,
192
- });
193
- }
194
- else {
195
- console.log(`\n${'═'.repeat(20)} DTF Deployed ${'═'.repeat(20)}`);
196
- console.log(`\n Name ${deployConfig.name}`);
197
- console.log(` Symbol ${deployConfig.symbol}`);
198
- console.log(` Address ${deployedAddress}`);
199
- console.log(` Chain ${chainLabel(chainId)}`);
200
- console.log(` Mode ${ungoverned ? 'Ungoverned (wallet-owned)' : 'Governed (Reserve DAO)'}`);
201
- console.log(` Tx ${deployHash}`);
202
- console.log(`\n Register ${registerUrl}`);
203
- }
204
- }
205
- // -- Basket validation --
206
- function validateBasket(basket) {
207
- if (basket.length === 0) {
208
- throw new Error('Basket must have at least one token.');
209
- }
210
- const totalWeight = basket.reduce((sum, item) => sum + item.weight, 0);
211
- if (Math.abs(totalWeight - 100) > 0.01) {
212
- throw new Error(`Basket weights must sum to 100%, got ${totalWeight}%.`);
213
- }
214
- // Detect duplicate symbols (catches "50% WETH, 50% WETH")
215
- const seen = new Set();
216
- for (const item of basket) {
217
- const key = item.address?.toLowerCase() ?? item.symbol.toUpperCase();
218
- if (seen.has(key)) {
219
- throw new Error(`Duplicate token in basket: ${item.symbol}`);
220
- }
221
- seen.add(key);
222
- }
223
- }
224
- // -- Basket amount calculation --
225
- function calculateBasketAmounts(resolvedBasket, prices, decimalMap, chainId) {
226
- // WHY: Collect all missing prices at once so user sees all failures, not just the first.
227
- const missing = [];
228
- for (const token of resolvedBasket) {
229
- const price = prices[token.address.toLowerCase()];
230
- if (!price || price <= 0) {
231
- missing.push(`${token.symbol} (${token.address})`);
232
- }
233
- }
234
- if (missing.length > 0) {
235
- throw new Error(`No price found for ${missing.join(', ')} on ${chainLabel(chainId)}. Cannot calculate basket amounts.`);
236
- }
237
- const basketAssets = [];
238
- const basketAmounts = [];
239
- for (const token of resolvedBasket) {
240
- const price = prices[token.address.toLowerCase()];
241
- const decimals = token.decimals ?? decimalMap[token.address.toLowerCase()] ?? 18;
242
- // amount_i = (weight_i / 100) / price_i, scaled to token decimals
243
- const amount = scaleToDecimals(token.weight / 100 / price, decimals);
244
- basketAssets.push(token.address);
245
- basketAmounts.push(amount.toString());
246
- }
247
- return { basketAssets, basketAmounts };
248
- }
249
- /**
250
- * Convert a floating-point value to a bigint scaled to the given decimals.
251
- * Uses string manipulation to avoid IEEE 754 precision loss for amounts
252
- * that would exceed Number.MAX_SAFE_INTEGER when multiplied.
253
- */
254
- function scaleToDecimals(value, decimals) {
255
- if (value <= 0)
256
- return 0n;
257
- // WHY: For small decimals (≤15), direct multiplication is safe within Number precision.
258
- // For 18 decimals, the result can exceed MAX_SAFE_INTEGER. Use string-based scaling.
259
- if (decimals <= 15) {
260
- return BigInt(Math.floor(value * 10 ** decimals));
261
- }
262
- // Split into integer and fractional parts via string to preserve precision
263
- const str = value.toFixed(20); // enough digits for 18 decimals
264
- const [intPart, fracPart = ''] = str.split('.');
265
- const padded = (fracPart + '0'.repeat(decimals)).slice(0, decimals);
266
- const combined = intPart + padded;
267
- // WHY: Remove leading zeros so BigInt doesn't interpret as octal, but keep at least '0'
268
- return BigInt(combined.replace(/^0+/, '') || '0');
269
- }
270
- /**
271
- * Parse ETH amount string to wei without floating-point precision loss.
272
- * Handles up to 18 decimal places.
273
- */
274
- function parseEthToWei(amount) {
275
- const str = amount.toFixed(18);
276
- const [intPart, fracPart = ''] = str.split('.');
277
- const padded = (fracPart + '0'.repeat(18)).slice(0, 18);
278
- return BigInt(intPart + padded);
279
- }
280
- // -- Basket parsing (3 formats) --
281
- function parseDeployConfig(args) {
282
- const configFile = getFlag(args, '--config');
283
- if (configFile) {
284
- return parseJsonConfig(configFile, args);
285
- }
286
- const name = getFlag(args, '--name');
287
- const symbol = getFlag(args, '--symbol');
288
- const basketRaw = getFlag(args, '--basket');
289
- const amountStr = getFlag(args, '--amount');
290
- const mandate = getFlag(args, '--mandate') ?? '';
291
- const ungoverned = args.includes('--ungoverned');
292
- if (!name || !symbol || !basketRaw || !amountStr) {
293
- console.log(DEPLOY_HELP);
294
- throw new Error('Missing required flags: --name, --symbol, --basket, --amount');
295
- }
296
- const amount = Number(amountStr);
297
- if (isNaN(amount) || amount <= 0) {
298
- throw new Error(`Invalid --amount: "${amountStr}". Must be a positive number (ETH).`);
299
- }
300
- // Auto-detect CSV by extension
301
- const basket = basketRaw.endsWith('.csv')
302
- ? parseBasketCsv(basketRaw)
303
- : parseBasketString(basketRaw);
304
- return { name, symbol, mandate, basket, amount, ungoverned };
305
- }
306
- function parseJsonConfig(filePath, args) {
307
- if (!existsSync(filePath)) {
308
- throw new Error(`Config file not found: ${filePath}`);
309
- }
310
- const raw = JSON.parse(readFileSync(filePath, 'utf-8'));
311
- const ungoverned = args.includes('--ungoverned');
312
- if (!raw.name || typeof raw.name !== 'string') {
313
- throw new Error('JSON config: "name" must be a non-empty string');
314
- }
315
- if (!raw.symbol || typeof raw.symbol !== 'string') {
316
- throw new Error('JSON config: "symbol" must be a non-empty string');
317
- }
318
- if (!Array.isArray(raw.basket) || raw.basket.length === 0) {
319
- throw new Error('JSON config: "basket" must be a non-empty array');
320
- }
321
- if (typeof raw.amount !== 'number' || raw.amount <= 0) {
322
- throw new Error('JSON config: "amount" must be a positive number');
323
- }
324
- const basket = raw.basket.map((item, i) => {
325
- if (!item || typeof item !== 'object') {
326
- throw new Error(`JSON config: basket[${i}] must be an object`);
327
- }
328
- const obj = item;
329
- if (typeof obj.symbol !== 'string') {
330
- throw new Error(`JSON config: basket[${i}].symbol must be a string`);
331
- }
332
- if (typeof obj.weight !== 'number' || obj.weight <= 0) {
333
- throw new Error(`JSON config: basket[${i}].weight must be a positive number`);
334
- }
335
- let address;
336
- if (typeof obj.address === 'string') {
337
- if (!isAddress(obj.address)) {
338
- throw new Error(`JSON config: basket[${i}].address "${obj.address}" is not a valid Ethereum address`);
339
- }
340
- address = obj.address;
341
- }
342
- return {
343
- symbol: obj.symbol,
344
- address,
345
- weight: obj.weight,
346
- };
347
- });
348
- return {
349
- name: raw.name,
350
- symbol: raw.symbol,
351
- mandate: typeof raw.mandate === 'string' ? raw.mandate : '',
352
- basket,
353
- amount: raw.amount,
354
- ungoverned,
355
- };
356
- }
357
- function parseBasketString(input) {
358
- // Format: "50% WETH, 30% USDC, 20% cbBTC"
359
- const items = input.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
360
- const basket = [];
361
- for (const item of items) {
362
- const match = item.match(/^(\d+(?:\.\d+)?)\s*%\s+(\S+)$/);
363
- if (!match) {
364
- throw new Error(`Invalid basket item: "${item}". Expected format: "50% WETH" (percentage followed by symbol or 0x address)`);
365
- }
366
- const weight = Number(match[1]);
367
- const symbolOrAddr = match[2];
368
- // WHY: A token like "0xWETH" starts with 0x but isn't a valid address.
369
- // Only treat as address if it passes full validation.
370
- const isAddr = symbolOrAddr.startsWith('0x') && isAddress(symbolOrAddr);
371
- basket.push({
372
- symbol: isAddr ? symbolOrAddr : symbolOrAddr,
373
- address: isAddr ? symbolOrAddr : undefined,
374
- weight,
375
- });
376
- }
377
- return basket;
378
- }
379
- function parseBasketCsv(filePath) {
380
- if (!existsSync(filePath)) {
381
- throw new Error(`CSV file not found: ${filePath}`);
382
- }
383
- const content = readFileSync(filePath, 'utf-8');
384
- const lines = content
385
- .split('\n')
386
- .map((l) => l.trim())
387
- .filter((l) => l.length > 0);
388
- if (lines.length < 2) {
389
- throw new Error('CSV file must have a header row and at least one data row');
390
- }
391
- // Skip header row
392
- const basket = [];
393
- for (let i = 1; i < lines.length; i++) {
394
- const parts = lines[i].split(',').map((p) => p.trim());
395
- if (parts.length < 3) {
396
- throw new Error(`Invalid CSV row ${i + 1}: expected 'symbol,address,weight' format`);
397
- }
398
- const symbol = parts[0];
399
- const address = parts[1];
400
- const weight = Number(parts[2]);
401
- if (!isAddress(address)) {
402
- throw new Error(`Invalid CSV row ${i + 1}: "${address}" is not a valid Ethereum address`);
403
- }
404
- if (address === '0x0000000000000000000000000000000000000000') {
405
- throw new Error(`Invalid CSV row ${i + 1}: zero address is not a valid token`);
406
- }
407
- if (isNaN(weight) || weight <= 0) {
408
- throw new Error(`Invalid CSV row ${i + 1}: weight "${parts[2]}" must be a positive number`);
409
- }
410
- basket.push({ symbol, address: address, weight });
411
- }
412
- return basket;
413
- }
414
- // -- Token resolution --
415
- function resolveBasketAddresses(basket, chainId) {
416
- return basket.map((item) => {
417
- if (item.address) {
418
- return { ...item, address: item.address };
419
- }
420
- const entry = resolveToken(chainId, item.symbol);
421
- if (!entry) {
422
- throw new Error(`Unknown token '${item.symbol}' on ${chainLabel(chainId)}. ` +
423
- `Use 'dtf deploy --list-tokens' to see available symbols, or use a raw 0x address.`);
424
- }
425
- return { ...item, address: entry.address, decimals: entry.decimals };
426
- });
427
- }
428
- // -- Output helpers --
429
- function outputDryRun(config, deployConfig, chainId, ungoverned, resolvedBasket, basketAmounts, prices, zapParams) {
430
- if (config.json) {
431
- printJson({
432
- dryRun: true,
433
- name: deployConfig.name,
434
- symbol: deployConfig.symbol,
435
- chain: chainId,
436
- chainLabel: chainLabel(chainId),
437
- mode: ungoverned ? 'ungoverned' : 'governed',
438
- amountEth: deployConfig.amount.toString(),
439
- basket: resolvedBasket.map((t, i) => ({
440
- symbol: t.symbol,
441
- address: t.address,
442
- weight: t.weight,
443
- amount: basketAmounts[i],
444
- priceUsd: prices[t.address.toLowerCase()] ?? null,
445
- })),
446
- zapParams,
447
- });
448
- }
449
- else {
450
- printHeader('Dry Run — Deploy Preview');
451
- console.log(`\n Name ${deployConfig.name}`);
452
- console.log(` Symbol ${deployConfig.symbol}`);
453
- console.log(` Chain ${chainLabel(chainId)}`);
454
- console.log(` Mode ${ungoverned ? 'Ungoverned (wallet-owned)' : 'Governed (Reserve DAO)'}`);
455
- console.log(` Amount ${deployConfig.amount} ETH`);
456
- console.log(` Basket:`);
457
- for (let i = 0; i < resolvedBasket.length; i++) {
458
- const t = resolvedBasket[i];
459
- const price = prices[t.address.toLowerCase()];
460
- console.log(` ${t.weight}% ${t.symbol} (${t.address})` +
461
- (price ? ` @ $${price}` : ''));
462
- }
463
- console.log('\n No transaction sent (--dry-run)');
464
- }
465
- }
466
- function listTokens(config) {
467
- const registry = getTokenRegistry(config.chainId);
468
- const entries = Object.entries(registry);
469
- if (config.json) {
470
- printJson(entries.map(([symbol, entry]) => ({
471
- symbol,
472
- address: entry.address,
473
- decimals: entry.decimals,
474
- })));
475
- return;
476
- }
477
- printHeader(`Available Tokens — ${chainLabel(config.chainId)}`);
478
- console.log();
479
- printTable([
480
- { header: 'Symbol', key: 'symbol' },
481
- { header: 'Address', key: 'address' },
482
- { header: 'Decimals', key: 'decimals', align: 'right' },
483
- ], entries.map(([symbol, entry]) => ({
484
- symbol,
485
- address: entry.address,
486
- decimals: String(entry.decimals),
487
- })));
488
- }
489
- function getFlag(args, flag) {
490
- const idx = args.indexOf(flag);
491
- if (idx === -1 || idx + 1 >= args.length)
492
- return undefined;
493
- return args[idx + 1];
494
- }
495
- //# sourceMappingURL=deploy.js.map