@vultisig/cli 0.22.5 → 0.23.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/CHANGELOG.md +27 -0
- package/dist/index.js +903 -31
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 0.23.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#464](https://github.com/vultisig/vultisig-sdk/pull/464) [`a6db82f`](https://github.com/vultisig/vultisig-sdk/commit/a6db82fd103ea8eea01a084cc8fbd787367db437) Thanks [@neavra](https://github.com/neavra)! - feat(sdk/vault): `signMsgDeposit` for THORChain/MayaChain LP add/remove; sdk-cli dispatches LP memos through it
|
|
8
|
+
|
|
9
|
+
Adds `vault.signMsgDeposit({chain, amountBaseUnits, memo})` to `VaultBase`, building a `THORChainDeposit` cosmos message via the existing keysign pipeline (passes `isDeposit: true` through `getChainSpecific`). Memo is opaque pass-through — LP add (`+:POOL[:PAIRED]`), LP remove (`-:POOL:BPS[:ASSET]`), and any future deposit-style intent flow through the same surface.
|
|
10
|
+
|
|
11
|
+
sdk-cli's `signNonEvmServerTx` now dispatches THORChain/MayaChain MsgDeposit envelopes by memo prefix: `=:` continues to route through `vault.swap` (Phase D), `+:` and `-:` route through the new `signThorMsgDepositLp` → `vault.signMsgDeposit`. Unsupported prefixes (LOAN, BOND, etc.) throw `NotImplemented` with the offending memo in the error message. Phase E in the envelope-parity progression; previously these memos threw at `parseThorSwapMemo`.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [[`fde60dc`](https://github.com/vultisig/vultisig-sdk/commit/fde60dcc9f9822e21c2dbaeaacb9afb45cff0955), [`a6db82f`](https://github.com/vultisig/vultisig-sdk/commit/a6db82fd103ea8eea01a084cc8fbd787367db437)]:
|
|
16
|
+
- @vultisig/sdk@0.23.0
|
|
17
|
+
- @vultisig/client-shared@0.2.7
|
|
18
|
+
- @vultisig/rujira@18.0.0
|
|
19
|
+
|
|
20
|
+
## 0.22.7
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- [#457](https://github.com/vultisig/vultisig-sdk/pull/457) [`680119e`](https://github.com/vultisig/vultisig-sdk/commit/680119e7392921b8aeaf859c85e811fb40a25054) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Add regression tests and drift guards for Bitcoin PSBT compilation, ChainKind signing-input alignment, generated protobuf headers, and CLI agent action names aligned with AGENTS.md.
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [[`680119e`](https://github.com/vultisig/vultisig-sdk/commit/680119e7392921b8aeaf859c85e811fb40a25054), [`5102976`](https://github.com/vultisig/vultisig-sdk/commit/5102976d7c13fa9578bbbc6e5122526cefc1ec66), [`b36eb62`](https://github.com/vultisig/vultisig-sdk/commit/b36eb62842051b8b2bae06f1e123a5ebcf6cad88)]:
|
|
27
|
+
- @vultisig/sdk@0.22.7
|
|
28
|
+
- @vultisig/core-chain@1.7.1
|
|
29
|
+
|
|
3
30
|
## 0.22.5
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -5395,8 +5395,399 @@ function getNativeTokenDecimals(chain) {
|
|
|
5395
5395
|
return decimals[chain] || 18;
|
|
5396
5396
|
}
|
|
5397
5397
|
|
|
5398
|
+
// ../../packages/core/chain/dist/Chain.js
|
|
5399
|
+
var EthereumL2Chain = {
|
|
5400
|
+
Arbitrum: "Arbitrum",
|
|
5401
|
+
Base: "Base",
|
|
5402
|
+
Blast: "Blast",
|
|
5403
|
+
Optimism: "Optimism",
|
|
5404
|
+
Zksync: "Zksync",
|
|
5405
|
+
Mantle: "Mantle"
|
|
5406
|
+
};
|
|
5407
|
+
var EvmChain = {
|
|
5408
|
+
...EthereumL2Chain,
|
|
5409
|
+
Avalanche: "Avalanche",
|
|
5410
|
+
CronosChain: "CronosChain",
|
|
5411
|
+
BSC: "BSC",
|
|
5412
|
+
Ethereum: "Ethereum",
|
|
5413
|
+
Polygon: "Polygon",
|
|
5414
|
+
Hyperliquid: "Hyperliquid",
|
|
5415
|
+
Sei: "Sei"
|
|
5416
|
+
};
|
|
5417
|
+
var UtxoChain;
|
|
5418
|
+
(function(UtxoChain2) {
|
|
5419
|
+
UtxoChain2["Bitcoin"] = "Bitcoin";
|
|
5420
|
+
UtxoChain2["BitcoinCash"] = "Bitcoin-Cash";
|
|
5421
|
+
UtxoChain2["Litecoin"] = "Litecoin";
|
|
5422
|
+
UtxoChain2["Dogecoin"] = "Dogecoin";
|
|
5423
|
+
UtxoChain2["Dash"] = "Dash";
|
|
5424
|
+
UtxoChain2["Zcash"] = "Zcash";
|
|
5425
|
+
})(UtxoChain || (UtxoChain = {}));
|
|
5426
|
+
var cosmosChainsByKind = {
|
|
5427
|
+
ibcEnabled: {
|
|
5428
|
+
Cosmos: "Cosmos",
|
|
5429
|
+
Osmosis: "Osmosis",
|
|
5430
|
+
Dydx: "Dydx",
|
|
5431
|
+
Kujira: "Kujira",
|
|
5432
|
+
Terra: "Terra",
|
|
5433
|
+
TerraClassic: "TerraClassic",
|
|
5434
|
+
Noble: "Noble",
|
|
5435
|
+
Akash: "Akash"
|
|
5436
|
+
},
|
|
5437
|
+
vaultBased: {
|
|
5438
|
+
THORChain: "THORChain",
|
|
5439
|
+
MayaChain: "MayaChain"
|
|
5440
|
+
}
|
|
5441
|
+
};
|
|
5442
|
+
var IbcEnabledCosmosChain = cosmosChainsByKind.ibcEnabled;
|
|
5443
|
+
var VaultBasedCosmosChain = cosmosChainsByKind.vaultBased;
|
|
5444
|
+
var CosmosChain = {
|
|
5445
|
+
...IbcEnabledCosmosChain,
|
|
5446
|
+
...VaultBasedCosmosChain
|
|
5447
|
+
};
|
|
5448
|
+
var OtherChain;
|
|
5449
|
+
(function(OtherChain2) {
|
|
5450
|
+
OtherChain2["Sui"] = "Sui";
|
|
5451
|
+
OtherChain2["Solana"] = "Solana";
|
|
5452
|
+
OtherChain2["Polkadot"] = "Polkadot";
|
|
5453
|
+
OtherChain2["Bittensor"] = "Bittensor";
|
|
5454
|
+
OtherChain2["Ton"] = "Ton";
|
|
5455
|
+
OtherChain2["Ripple"] = "Ripple";
|
|
5456
|
+
OtherChain2["Tron"] = "Tron";
|
|
5457
|
+
OtherChain2["Cardano"] = "Cardano";
|
|
5458
|
+
OtherChain2["QBTC"] = "QBTC";
|
|
5459
|
+
})(OtherChain || (OtherChain = {}));
|
|
5460
|
+
var Chain9 = {
|
|
5461
|
+
...EvmChain,
|
|
5462
|
+
...UtxoChain,
|
|
5463
|
+
...CosmosChain,
|
|
5464
|
+
...OtherChain
|
|
5465
|
+
};
|
|
5466
|
+
var UtxoBasedChain = [
|
|
5467
|
+
...Object.values(UtxoChain),
|
|
5468
|
+
OtherChain.Cardano
|
|
5469
|
+
];
|
|
5470
|
+
var defaultChains = [
|
|
5471
|
+
Chain9.Bitcoin,
|
|
5472
|
+
Chain9.Ethereum,
|
|
5473
|
+
Chain9.THORChain,
|
|
5474
|
+
Chain9.Solana,
|
|
5475
|
+
Chain9.BSC
|
|
5476
|
+
];
|
|
5477
|
+
|
|
5478
|
+
// ../../packages/core/chain/dist/ChainKind.js
|
|
5479
|
+
var chainKindRecord = {
|
|
5480
|
+
[EvmChain.Arbitrum]: "evm",
|
|
5481
|
+
[EvmChain.Avalanche]: "evm",
|
|
5482
|
+
[EvmChain.Base]: "evm",
|
|
5483
|
+
[EvmChain.CronosChain]: "evm",
|
|
5484
|
+
[EvmChain.BSC]: "evm",
|
|
5485
|
+
[EvmChain.Blast]: "evm",
|
|
5486
|
+
[EvmChain.Ethereum]: "evm",
|
|
5487
|
+
[EvmChain.Optimism]: "evm",
|
|
5488
|
+
[EvmChain.Polygon]: "evm",
|
|
5489
|
+
[EvmChain.Zksync]: "evm",
|
|
5490
|
+
[EvmChain.Mantle]: "evm",
|
|
5491
|
+
[EvmChain.Hyperliquid]: "evm",
|
|
5492
|
+
[EvmChain.Sei]: "evm",
|
|
5493
|
+
[UtxoChain.Bitcoin]: "utxo",
|
|
5494
|
+
[UtxoChain.BitcoinCash]: "utxo",
|
|
5495
|
+
[UtxoChain.Litecoin]: "utxo",
|
|
5496
|
+
[UtxoChain.Dogecoin]: "utxo",
|
|
5497
|
+
[UtxoChain.Dash]: "utxo",
|
|
5498
|
+
[UtxoChain.Zcash]: "utxo",
|
|
5499
|
+
[CosmosChain.THORChain]: "cosmos",
|
|
5500
|
+
[CosmosChain.Cosmos]: "cosmos",
|
|
5501
|
+
[CosmosChain.Osmosis]: "cosmos",
|
|
5502
|
+
[CosmosChain.MayaChain]: "cosmos",
|
|
5503
|
+
[CosmosChain.Dydx]: "cosmos",
|
|
5504
|
+
[CosmosChain.Kujira]: "cosmos",
|
|
5505
|
+
[CosmosChain.Terra]: "cosmos",
|
|
5506
|
+
[CosmosChain.TerraClassic]: "cosmos",
|
|
5507
|
+
[CosmosChain.Noble]: "cosmos",
|
|
5508
|
+
[CosmosChain.Akash]: "cosmos",
|
|
5509
|
+
[OtherChain.Sui]: "sui",
|
|
5510
|
+
[OtherChain.Solana]: "solana",
|
|
5511
|
+
[OtherChain.Polkadot]: "polkadot",
|
|
5512
|
+
[OtherChain.Bittensor]: "bittensor",
|
|
5513
|
+
[OtherChain.Ton]: "ton",
|
|
5514
|
+
[OtherChain.Ripple]: "ripple",
|
|
5515
|
+
[OtherChain.Tron]: "tron",
|
|
5516
|
+
[OtherChain.Cardano]: "cardano",
|
|
5517
|
+
[OtherChain.QBTC]: "qbtc"
|
|
5518
|
+
};
|
|
5519
|
+
function getChainKind(chain) {
|
|
5520
|
+
return chainKindRecord[chain];
|
|
5521
|
+
}
|
|
5522
|
+
|
|
5523
|
+
// ../../packages/lib/utils/dist/record/recordMap.js
|
|
5524
|
+
function recordMap(record, fn) {
|
|
5525
|
+
return Object.fromEntries(Object.entries(record).map(([key, value]) => [
|
|
5526
|
+
key,
|
|
5527
|
+
fn(value, key)
|
|
5528
|
+
]));
|
|
5529
|
+
}
|
|
5530
|
+
|
|
5531
|
+
// ../../packages/lib/utils/dist/record/makeRecord/index.js
|
|
5532
|
+
var makeRecord = (keys, getValue) => {
|
|
5533
|
+
const record = {};
|
|
5534
|
+
keys.forEach((key, index) => {
|
|
5535
|
+
record[key] = getValue(key, index);
|
|
5536
|
+
});
|
|
5537
|
+
return record;
|
|
5538
|
+
};
|
|
5539
|
+
|
|
5540
|
+
// ../../packages/core/chain/dist/chains/cosmos/thor/kujira-merge/index.js
|
|
5541
|
+
var kujiraCoinsMigratedToThorChain = [
|
|
5542
|
+
"kuji",
|
|
5543
|
+
"rkuji",
|
|
5544
|
+
"fuzn",
|
|
5545
|
+
"nstk",
|
|
5546
|
+
"wink",
|
|
5547
|
+
"lvn"
|
|
5548
|
+
];
|
|
5549
|
+
var kujiraCoinsMigratedToThorChainMetadata = {
|
|
5550
|
+
kuji: {
|
|
5551
|
+
ticker: "KUJI",
|
|
5552
|
+
logo: "kuji",
|
|
5553
|
+
priceProviderId: "kujira"
|
|
5554
|
+
},
|
|
5555
|
+
rkuji: {
|
|
5556
|
+
ticker: "rKUJI",
|
|
5557
|
+
logo: "rkuji.png",
|
|
5558
|
+
priceProviderId: "kujira"
|
|
5559
|
+
},
|
|
5560
|
+
fuzn: {
|
|
5561
|
+
ticker: "FUZN",
|
|
5562
|
+
logo: "fuzn.png",
|
|
5563
|
+
priceProviderId: "fuzion"
|
|
5564
|
+
},
|
|
5565
|
+
lvn: {
|
|
5566
|
+
ticker: "LVN",
|
|
5567
|
+
logo: "levana",
|
|
5568
|
+
priceProviderId: "levana-protocol"
|
|
5569
|
+
},
|
|
5570
|
+
nstk: {
|
|
5571
|
+
ticker: "NSTK",
|
|
5572
|
+
logo: "nstk.png",
|
|
5573
|
+
priceProviderId: "unstake-fi"
|
|
5574
|
+
},
|
|
5575
|
+
wink: {
|
|
5576
|
+
ticker: "WINK",
|
|
5577
|
+
logo: "wink.png",
|
|
5578
|
+
priceProviderId: "winkhub"
|
|
5579
|
+
}
|
|
5580
|
+
};
|
|
5581
|
+
var kujiraCoinMigratedToThorChainDestinationId = makeRecord(kujiraCoinsMigratedToThorChain, (id) => `thor.${id}`);
|
|
5582
|
+
|
|
5583
|
+
// ../../packages/core/chain/dist/coin/chainFeeCoin.js
|
|
5584
|
+
var ether = {
|
|
5585
|
+
ticker: "ETH",
|
|
5586
|
+
logo: "eth",
|
|
5587
|
+
decimals: 18,
|
|
5588
|
+
priceProviderId: "ethereum"
|
|
5589
|
+
};
|
|
5590
|
+
var leanChainFeeCoin = {
|
|
5591
|
+
[Chain9.Bitcoin]: {
|
|
5592
|
+
ticker: "BTC",
|
|
5593
|
+
logo: "btc",
|
|
5594
|
+
decimals: 8,
|
|
5595
|
+
priceProviderId: "bitcoin"
|
|
5596
|
+
},
|
|
5597
|
+
[Chain9.BitcoinCash]: {
|
|
5598
|
+
ticker: "BCH",
|
|
5599
|
+
logo: "bch",
|
|
5600
|
+
decimals: 8,
|
|
5601
|
+
priceProviderId: "bitcoin-cash"
|
|
5602
|
+
},
|
|
5603
|
+
[Chain9.Litecoin]: {
|
|
5604
|
+
ticker: "LTC",
|
|
5605
|
+
logo: "ltc",
|
|
5606
|
+
decimals: 8,
|
|
5607
|
+
priceProviderId: "litecoin"
|
|
5608
|
+
},
|
|
5609
|
+
[Chain9.Dogecoin]: {
|
|
5610
|
+
ticker: "DOGE",
|
|
5611
|
+
logo: "doge",
|
|
5612
|
+
decimals: 8,
|
|
5613
|
+
priceProviderId: "dogecoin"
|
|
5614
|
+
},
|
|
5615
|
+
[Chain9.Dash]: {
|
|
5616
|
+
ticker: "DASH",
|
|
5617
|
+
logo: "dash",
|
|
5618
|
+
decimals: 8,
|
|
5619
|
+
priceProviderId: "dash"
|
|
5620
|
+
},
|
|
5621
|
+
[Chain9.Ripple]: {
|
|
5622
|
+
ticker: "XRP",
|
|
5623
|
+
logo: "xrp",
|
|
5624
|
+
decimals: 6,
|
|
5625
|
+
priceProviderId: "ripple"
|
|
5626
|
+
},
|
|
5627
|
+
[Chain9.THORChain]: {
|
|
5628
|
+
ticker: "RUNE",
|
|
5629
|
+
logo: "rune",
|
|
5630
|
+
decimals: 8,
|
|
5631
|
+
priceProviderId: "thorchain"
|
|
5632
|
+
},
|
|
5633
|
+
[Chain9.MayaChain]: {
|
|
5634
|
+
ticker: "CACAO",
|
|
5635
|
+
logo: "cacao",
|
|
5636
|
+
decimals: 10,
|
|
5637
|
+
priceProviderId: "cacao"
|
|
5638
|
+
},
|
|
5639
|
+
[Chain9.Solana]: {
|
|
5640
|
+
ticker: "SOL",
|
|
5641
|
+
logo: "solana",
|
|
5642
|
+
decimals: 9,
|
|
5643
|
+
priceProviderId: "solana"
|
|
5644
|
+
},
|
|
5645
|
+
[Chain9.Ton]: {
|
|
5646
|
+
ticker: "TON",
|
|
5647
|
+
logo: "ton",
|
|
5648
|
+
decimals: 9,
|
|
5649
|
+
priceProviderId: "the-open-network"
|
|
5650
|
+
},
|
|
5651
|
+
[Chain9.Ethereum]: ether,
|
|
5652
|
+
[Chain9.Avalanche]: {
|
|
5653
|
+
ticker: "AVAX",
|
|
5654
|
+
logo: "avax",
|
|
5655
|
+
decimals: 18,
|
|
5656
|
+
priceProviderId: "avalanche-2"
|
|
5657
|
+
},
|
|
5658
|
+
[Chain9.BSC]: {
|
|
5659
|
+
ticker: "BNB",
|
|
5660
|
+
logo: "bsc",
|
|
5661
|
+
decimals: 18,
|
|
5662
|
+
priceProviderId: "binancecoin"
|
|
5663
|
+
},
|
|
5664
|
+
[Chain9.Polygon]: {
|
|
5665
|
+
ticker: "POL",
|
|
5666
|
+
logo: "polygon",
|
|
5667
|
+
decimals: 18,
|
|
5668
|
+
priceProviderId: "polygon-ecosystem-token"
|
|
5669
|
+
},
|
|
5670
|
+
[Chain9.CronosChain]: {
|
|
5671
|
+
ticker: "CRO",
|
|
5672
|
+
logo: "cro",
|
|
5673
|
+
decimals: 18,
|
|
5674
|
+
priceProviderId: "crypto-com-chain"
|
|
5675
|
+
},
|
|
5676
|
+
[Chain9.Dydx]: {
|
|
5677
|
+
ticker: "DYDX",
|
|
5678
|
+
logo: "dydx",
|
|
5679
|
+
decimals: 18,
|
|
5680
|
+
priceProviderId: "dydx-chain"
|
|
5681
|
+
},
|
|
5682
|
+
[Chain9.Kujira]: {
|
|
5683
|
+
...kujiraCoinsMigratedToThorChainMetadata.kuji,
|
|
5684
|
+
decimals: 6
|
|
5685
|
+
},
|
|
5686
|
+
[Chain9.Terra]: {
|
|
5687
|
+
ticker: "LUNA",
|
|
5688
|
+
logo: "luna",
|
|
5689
|
+
decimals: 6,
|
|
5690
|
+
priceProviderId: "terra-luna-2"
|
|
5691
|
+
},
|
|
5692
|
+
[Chain9.TerraClassic]: {
|
|
5693
|
+
ticker: "LUNC",
|
|
5694
|
+
logo: "lunc",
|
|
5695
|
+
decimals: 6,
|
|
5696
|
+
priceProviderId: "terra-luna"
|
|
5697
|
+
},
|
|
5698
|
+
[Chain9.Sui]: {
|
|
5699
|
+
ticker: "SUI",
|
|
5700
|
+
logo: "sui",
|
|
5701
|
+
decimals: 9,
|
|
5702
|
+
priceProviderId: "sui"
|
|
5703
|
+
},
|
|
5704
|
+
[Chain9.Polkadot]: {
|
|
5705
|
+
ticker: "DOT",
|
|
5706
|
+
logo: "dot",
|
|
5707
|
+
decimals: 10,
|
|
5708
|
+
priceProviderId: "polkadot"
|
|
5709
|
+
},
|
|
5710
|
+
[Chain9.Bittensor]: {
|
|
5711
|
+
ticker: "TAO",
|
|
5712
|
+
logo: "bittensor",
|
|
5713
|
+
decimals: 9,
|
|
5714
|
+
priceProviderId: "bittensor"
|
|
5715
|
+
},
|
|
5716
|
+
[Chain9.Noble]: {
|
|
5717
|
+
ticker: "USDC",
|
|
5718
|
+
logo: "noble",
|
|
5719
|
+
decimals: 6,
|
|
5720
|
+
priceProviderId: "usd-coin"
|
|
5721
|
+
},
|
|
5722
|
+
[Chain9.Akash]: {
|
|
5723
|
+
ticker: "AKT",
|
|
5724
|
+
logo: "akash",
|
|
5725
|
+
decimals: 6,
|
|
5726
|
+
priceProviderId: "akash-network"
|
|
5727
|
+
},
|
|
5728
|
+
[Chain9.Cosmos]: {
|
|
5729
|
+
ticker: "ATOM",
|
|
5730
|
+
logo: "atom",
|
|
5731
|
+
decimals: 6,
|
|
5732
|
+
priceProviderId: "cosmos"
|
|
5733
|
+
},
|
|
5734
|
+
[Chain9.Osmosis]: {
|
|
5735
|
+
ticker: "OSMO",
|
|
5736
|
+
logo: "osmo",
|
|
5737
|
+
decimals: 6,
|
|
5738
|
+
priceProviderId: "osmosis"
|
|
5739
|
+
},
|
|
5740
|
+
[Chain9.Tron]: {
|
|
5741
|
+
ticker: "TRX",
|
|
5742
|
+
logo: "tron",
|
|
5743
|
+
decimals: 6,
|
|
5744
|
+
priceProviderId: "tron"
|
|
5745
|
+
},
|
|
5746
|
+
...recordMap(EthereumL2Chain, () => ether),
|
|
5747
|
+
[Chain9.Zcash]: {
|
|
5748
|
+
ticker: "ZEC",
|
|
5749
|
+
logo: "zec",
|
|
5750
|
+
decimals: 8,
|
|
5751
|
+
priceProviderId: "zcash"
|
|
5752
|
+
},
|
|
5753
|
+
[Chain9.Cardano]: {
|
|
5754
|
+
ticker: "ADA",
|
|
5755
|
+
logo: "ada",
|
|
5756
|
+
decimals: 6,
|
|
5757
|
+
priceProviderId: "cardano"
|
|
5758
|
+
},
|
|
5759
|
+
[Chain9.Mantle]: {
|
|
5760
|
+
ticker: "MNT",
|
|
5761
|
+
logo: "mantle",
|
|
5762
|
+
decimals: 18,
|
|
5763
|
+
priceProviderId: "mantle"
|
|
5764
|
+
},
|
|
5765
|
+
[Chain9.Hyperliquid]: {
|
|
5766
|
+
ticker: "HYPE",
|
|
5767
|
+
logo: "hyperliquid",
|
|
5768
|
+
decimals: 18,
|
|
5769
|
+
priceProviderId: "hyperliquid"
|
|
5770
|
+
},
|
|
5771
|
+
[Chain9.Sei]: {
|
|
5772
|
+
ticker: "SEI",
|
|
5773
|
+
logo: "sei",
|
|
5774
|
+
decimals: 18,
|
|
5775
|
+
priceProviderId: "sei-network"
|
|
5776
|
+
},
|
|
5777
|
+
[Chain9.QBTC]: {
|
|
5778
|
+
ticker: "QBTC",
|
|
5779
|
+
logo: "qbtc",
|
|
5780
|
+
decimals: 6,
|
|
5781
|
+
priceProviderId: "qbtc-testnet"
|
|
5782
|
+
}
|
|
5783
|
+
};
|
|
5784
|
+
var chainFeeCoin = recordMap(leanChainFeeCoin, (coin, chain) => ({
|
|
5785
|
+
...coin,
|
|
5786
|
+
chain
|
|
5787
|
+
}));
|
|
5788
|
+
|
|
5398
5789
|
// src/agent/executor.ts
|
|
5399
|
-
import { Chain as
|
|
5790
|
+
import { Chain as Chain10, VaultError as VaultError3, VaultErrorCode as VaultErrorCode3, Vultisig as VultisigSdk } from "@vultisig/sdk";
|
|
5400
5791
|
|
|
5401
5792
|
// ../../node_modules/viem/_esm/index.js
|
|
5402
5793
|
init_formatUnits();
|
|
@@ -5557,6 +5948,45 @@ function sleep2(ms) {
|
|
|
5557
5948
|
}
|
|
5558
5949
|
|
|
5559
5950
|
// src/agent/executor.ts
|
|
5951
|
+
var THOR_MEMO_CHAIN_TO_ENUM = {
|
|
5952
|
+
BTC: Chain10.Bitcoin,
|
|
5953
|
+
ETH: Chain10.Ethereum,
|
|
5954
|
+
BSC: Chain10.BSC,
|
|
5955
|
+
AVAX: Chain10.Avalanche,
|
|
5956
|
+
BASE: Chain10.Base,
|
|
5957
|
+
// L2 — THORChain routinely quotes Base destinations (PR #439 review finding 1)
|
|
5958
|
+
ARB: Chain10.Arbitrum,
|
|
5959
|
+
// L1-via-bridge path (PR #439 review finding 1)
|
|
5960
|
+
BCH: Chain10.BitcoinCash,
|
|
5961
|
+
LTC: Chain10.Litecoin,
|
|
5962
|
+
DOGE: Chain10.Dogecoin,
|
|
5963
|
+
GAIA: Chain10.Cosmos,
|
|
5964
|
+
THOR: Chain10.THORChain,
|
|
5965
|
+
RUNE: Chain10.THORChain,
|
|
5966
|
+
XRP: Chain10.Ripple,
|
|
5967
|
+
DASH: Chain10.Dash,
|
|
5968
|
+
ZEC: Chain10.Zcash,
|
|
5969
|
+
MAYA: Chain10.MayaChain,
|
|
5970
|
+
CACAO: Chain10.MayaChain
|
|
5971
|
+
};
|
|
5972
|
+
var THOR_MEMO_ASSET_SHORTCUTS = {
|
|
5973
|
+
b: "BTC.BTC",
|
|
5974
|
+
e: "ETH.ETH",
|
|
5975
|
+
s: "BSC.BNB",
|
|
5976
|
+
a: "AVAX.AVAX",
|
|
5977
|
+
c: "BCH.BCH",
|
|
5978
|
+
l: "LTC.LTC",
|
|
5979
|
+
d: "DOGE.DOGE",
|
|
5980
|
+
g: "GAIA.ATOM",
|
|
5981
|
+
r: "THOR.RUNE",
|
|
5982
|
+
x: "XRP.XRP",
|
|
5983
|
+
cacao: "MAYA.CACAO",
|
|
5984
|
+
dash: "DASH.DASH",
|
|
5985
|
+
zec: "ZEC.ZEC"
|
|
5986
|
+
// BASE / ARB don't have documented single-letter shortcuts; THORChain
|
|
5987
|
+
// emits these as the full CHAIN.ASSET form in memos. Listed in
|
|
5988
|
+
// THOR_MEMO_CHAIN_TO_ENUM only.
|
|
5989
|
+
};
|
|
5560
5990
|
var EVM_CHAINS = /* @__PURE__ */ new Set([
|
|
5561
5991
|
"Ethereum",
|
|
5562
5992
|
"BSC",
|
|
@@ -5592,6 +6022,12 @@ var AgentExecutor = class {
|
|
|
5592
6022
|
/** Owning SDK (optional); used for address book backed by app storage */
|
|
5593
6023
|
vultisig;
|
|
5594
6024
|
pendingPayloads = /* @__PURE__ */ new Map();
|
|
6025
|
+
/**
|
|
6026
|
+
* Buffered legs for a 2-leg mcp-ts execute_* envelope (approve + main).
|
|
6027
|
+
* Populated by storeServerTransaction when both `approvalTxArgs` and
|
|
6028
|
+
* `txArgs` are present; consumed and cleared by signMultiLeg.
|
|
6029
|
+
*/
|
|
6030
|
+
pendingLegs = [];
|
|
5595
6031
|
password = null;
|
|
5596
6032
|
verbose;
|
|
5597
6033
|
stateStore = null;
|
|
@@ -5621,13 +6057,46 @@ var AgentExecutor = class {
|
|
|
5621
6057
|
`[executor] storeServerTransaction called, keys: ${Object.keys(txReadyData || {}).join(",")}
|
|
5622
6058
|
`
|
|
5623
6059
|
);
|
|
5624
|
-
if (txReadyData?.approvalTxArgs) {
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
6060
|
+
if (txReadyData?.approvalTxArgs && txReadyData?.txArgs) {
|
|
6061
|
+
const approvalChain = resolveChainFromTxReady(txReadyData.approvalTxArgs);
|
|
6062
|
+
const mainChain = resolveChainFromTxReady(txReadyData.txArgs);
|
|
6063
|
+
const parentChain = resolveChainFromTxReady(txReadyData);
|
|
6064
|
+
if (!approvalChain || !mainChain || approvalChain !== mainChain || parentChain && parentChain !== approvalChain) {
|
|
6065
|
+
if (this.verbose)
|
|
6066
|
+
process.stderr.write(
|
|
6067
|
+
`[executor] rejecting multi-leg envelope with inconsistent chain metadata: parent=${parentChain ?? "unresolved"} approval=${approvalChain ?? "unresolved"} main=${mainChain ?? "unresolved"}
|
|
5628
6068
|
`
|
|
5629
|
-
|
|
5630
|
-
|
|
6069
|
+
);
|
|
6070
|
+
return false;
|
|
6071
|
+
}
|
|
6072
|
+
const chain2 = approvalChain;
|
|
6073
|
+
if (!EVM_CHAINS.has(chain2)) {
|
|
6074
|
+
if (this.verbose)
|
|
6075
|
+
process.stderr.write(
|
|
6076
|
+
`[executor] rejecting multi-leg envelope on non-EVM chain ${chain2}: signMultiLeg is EVM-only
|
|
6077
|
+
`
|
|
6078
|
+
);
|
|
6079
|
+
return false;
|
|
6080
|
+
}
|
|
6081
|
+
this.pendingLegs = [
|
|
6082
|
+
{
|
|
6083
|
+
txArgs: txReadyData.approvalTxArgs,
|
|
6084
|
+
parent: txReadyData,
|
|
6085
|
+
kind: "approve"
|
|
6086
|
+
},
|
|
6087
|
+
{ txArgs: txReadyData.txArgs, parent: txReadyData, kind: "main" }
|
|
6088
|
+
];
|
|
6089
|
+
this.pendingPayloads.clear();
|
|
6090
|
+
this.pendingPayloads.set("latest", {
|
|
6091
|
+
payload: { __serverTx: true, __multiLeg: true, ...txReadyData },
|
|
6092
|
+
coin: { chain: chain2, address: "", decimals: 18, ticker: "" },
|
|
6093
|
+
chain: chain2,
|
|
6094
|
+
timestamp: Date.now()
|
|
6095
|
+
});
|
|
6096
|
+
if (this.verbose)
|
|
6097
|
+
process.stderr.write(`[executor] stored multi-leg envelope: chain=${chain2}, legs=2 (approve, main)
|
|
6098
|
+
`);
|
|
6099
|
+
return true;
|
|
5631
6100
|
}
|
|
5632
6101
|
const nestedTx = extractNestedTx(txReadyData);
|
|
5633
6102
|
if (nestedTx?.status === "error" || nestedTx?.error) {
|
|
@@ -5636,13 +6105,34 @@ var AgentExecutor = class {
|
|
|
5636
6105
|
`);
|
|
5637
6106
|
return false;
|
|
5638
6107
|
}
|
|
6108
|
+
if (!nestedTx && txReadyData && typeof txReadyData === "object") {
|
|
6109
|
+
const txArgs = txReadyData.txArgs;
|
|
6110
|
+
if (txArgs && typeof txArgs === "object" && typeof txArgs.to === "string" && typeof txArgs.amount === "string") {
|
|
6111
|
+
const chain2 = resolveChainFromTxReady(txReadyData) || Chain10.Ethereum;
|
|
6112
|
+
if (getChainKind(chain2) !== "evm") {
|
|
6113
|
+
this.pendingPayloads.clear();
|
|
6114
|
+
this.pendingPayloads.set("latest", {
|
|
6115
|
+
payload: { __serverTx: true, ...txReadyData },
|
|
6116
|
+
coin: { chain: chain2, address: "", decimals: 18, ticker: "" },
|
|
6117
|
+
chain: chain2,
|
|
6118
|
+
timestamp: Date.now()
|
|
6119
|
+
});
|
|
6120
|
+
if (this.verbose)
|
|
6121
|
+
process.stderr.write(
|
|
6122
|
+
`[executor] Stored non-EVM server tx for chain ${chain2} (kind=${getChainKind(chain2)})
|
|
6123
|
+
`
|
|
6124
|
+
);
|
|
6125
|
+
return true;
|
|
6126
|
+
}
|
|
6127
|
+
}
|
|
6128
|
+
}
|
|
5639
6129
|
if (!nestedTx) {
|
|
5640
6130
|
if (this.verbose)
|
|
5641
6131
|
process.stderr.write(`[executor] storeServerTransaction: no swap_tx/send_tx/tx/txArgs.tx found in data
|
|
5642
6132
|
`);
|
|
5643
6133
|
return false;
|
|
5644
6134
|
}
|
|
5645
|
-
const chain = resolveChainFromTxReady(txReadyData) ||
|
|
6135
|
+
const chain = resolveChainFromTxReady(txReadyData) || Chain10.Ethereum;
|
|
5646
6136
|
this.pendingPayloads.clear();
|
|
5647
6137
|
this.pendingPayloads.set("latest", {
|
|
5648
6138
|
payload: { __serverTx: true, ...txReadyData },
|
|
@@ -5871,7 +6361,16 @@ var AgentExecutor = class {
|
|
|
5871
6361
|
throw new Error("Pending transaction is not a server-built tx (no __serverTx flag).");
|
|
5872
6362
|
}
|
|
5873
6363
|
let result;
|
|
5874
|
-
if (
|
|
6364
|
+
if (payload.__multiLeg) {
|
|
6365
|
+
if (this.pendingLegs.length !== 2) {
|
|
6366
|
+
throw new VaultError3(
|
|
6367
|
+
VaultErrorCode3.InvalidConfig,
|
|
6368
|
+
`signMultiLeg: expected 2 pending legs, got ${this.pendingLegs.length}`
|
|
6369
|
+
);
|
|
6370
|
+
}
|
|
6371
|
+
result = await this.signMultiLeg(payload, chain, {});
|
|
6372
|
+
}
|
|
6373
|
+
if (!result && chain === "Solana" && (payload.swap_tx || payload.provider)) {
|
|
5875
6374
|
try {
|
|
5876
6375
|
result = await this.buildAndSignSolanaSwapLocally(payload);
|
|
5877
6376
|
} catch (e) {
|
|
@@ -5890,10 +6389,223 @@ var AgentExecutor = class {
|
|
|
5890
6389
|
});
|
|
5891
6390
|
}
|
|
5892
6391
|
/**
|
|
5893
|
-
*
|
|
5894
|
-
*
|
|
6392
|
+
* Dispatch a server-built tx_ready envelope to the chain-kind-specific
|
|
6393
|
+
* signer. EVM stays in `signEvmServerTx` (the existing PR #422 + PR #435
|
|
6394
|
+
* code, with EVM nonce/lock plumbing). Non-EVM kinds parse the envelope
|
|
6395
|
+
* via `parseNonEvmEnvelope` and route through `vault.send`, which is
|
|
6396
|
+
* already chain-agnostic via `VaultBase.prepareSendTx` virtuals.
|
|
6397
|
+
*
|
|
6398
|
+
* Phase D — see task `100526-sdk-cli-non-evm-signing.md`.
|
|
5895
6399
|
*/
|
|
5896
6400
|
async signServerTx(serverTxData, defaultChain, params) {
|
|
6401
|
+
const chain = resolveChainFromTxReady(serverTxData) || defaultChain;
|
|
6402
|
+
const chainKind = getChainKind(chain);
|
|
6403
|
+
if (chainKind === "evm") {
|
|
6404
|
+
return this.signEvmServerTx(serverTxData, defaultChain, params);
|
|
6405
|
+
}
|
|
6406
|
+
return this.signNonEvmServerTx(serverTxData, chain);
|
|
6407
|
+
}
|
|
6408
|
+
/**
|
|
6409
|
+
* Non-EVM signing path: parse the agent's tx_ready envelope into a
|
|
6410
|
+
* `vault.send`-shaped argument bag and call through. The SDK already
|
|
6411
|
+
* handles per-chain prepare/sign/broadcast internally via
|
|
6412
|
+
* `VaultBase.prepareSendTx` virtuals — sdk-cli only owns envelope
|
|
6413
|
+
* parsing here, not chain-specific signing logic.
|
|
6414
|
+
*
|
|
6415
|
+
* THORChain / MayaChain MsgDeposit envelopes (msg_type='deposit',
|
|
6416
|
+
* to='') are routed through `vault.swap` because the agent's intent
|
|
6417
|
+
* is a swap — the memo (`=:CHAIN.ASSET:DEST::v0:slippage`) carries
|
|
6418
|
+
* the routing. We parse the memo to reconstruct vault.swap's
|
|
6419
|
+
* fromChain / fromSymbol / toChain / toSymbol / amount args. The SDK
|
|
6420
|
+
* then builds the MsgDeposit cosmos tx internally. Vultiagent uses an
|
|
6421
|
+
* equivalent custom helper (`buildSignBroadcastThorchainLpDeposit`);
|
|
6422
|
+
* we reuse the public `vault.swap` surface to avoid expanding the SDK.
|
|
6423
|
+
*/
|
|
6424
|
+
async signNonEvmServerTx(serverTxData, chain) {
|
|
6425
|
+
if (this.vault.isEncrypted && !this.vault.isUnlocked?.()) {
|
|
6426
|
+
if (this.password) {
|
|
6427
|
+
await this.vault.unlock?.(this.password);
|
|
6428
|
+
}
|
|
6429
|
+
}
|
|
6430
|
+
const txArgs = serverTxData?.txArgs ?? {};
|
|
6431
|
+
if (typeof txArgs.chain === "string" && txArgs.chain !== chain) {
|
|
6432
|
+
throw new VaultError3(
|
|
6433
|
+
VaultErrorCode3.InvalidConfig,
|
|
6434
|
+
`signNonEvmServerTx: dispatcher chain '${chain}' disagrees with envelope chain '${txArgs.chain}'`
|
|
6435
|
+
);
|
|
6436
|
+
}
|
|
6437
|
+
if (txArgs.msg_type === "deposit" && (chain === Chain10.THORChain || chain === Chain10.MayaChain)) {
|
|
6438
|
+
const memo = typeof txArgs.memo === "string" ? txArgs.memo : "";
|
|
6439
|
+
if (memo.startsWith("=:")) {
|
|
6440
|
+
return this.signThorMsgDepositSwap(serverTxData, chain);
|
|
6441
|
+
}
|
|
6442
|
+
if (memo.startsWith("+:") || memo.startsWith("-:")) {
|
|
6443
|
+
return this.signThorMsgDepositLp(serverTxData, chain);
|
|
6444
|
+
}
|
|
6445
|
+
throw new VaultError3(
|
|
6446
|
+
VaultErrorCode3.NotImplemented,
|
|
6447
|
+
`signNonEvmServerTx: MsgDeposit memo prefix not supported on ${chain}: '${memo}'. Supported prefixes: '=:' (swap), '+:' (LP add), '-:' (LP remove). Loan / validator ops are out of scope.`
|
|
6448
|
+
);
|
|
6449
|
+
}
|
|
6450
|
+
const args = parseNonEvmEnvelope(serverTxData, chain);
|
|
6451
|
+
if (this.verbose)
|
|
6452
|
+
process.stderr.write(
|
|
6453
|
+
`[sign_non_evm_server_tx] chain=${chain}, to=${args.to}, amount=${args.amount}${args.symbol ? ` ${args.symbol}` : ""}, memo=${args.memo ? `"${args.memo}"` : "(none)"}
|
|
6454
|
+
`
|
|
6455
|
+
);
|
|
6456
|
+
const result = await this.vault.send({
|
|
6457
|
+
chain,
|
|
6458
|
+
to: args.to,
|
|
6459
|
+
amount: args.amount,
|
|
6460
|
+
symbol: args.symbol,
|
|
6461
|
+
memo: args.memo
|
|
6462
|
+
});
|
|
6463
|
+
if (result.dryRun) {
|
|
6464
|
+
throw new VaultError3(
|
|
6465
|
+
VaultErrorCode3.InvalidConfig,
|
|
6466
|
+
"signNonEvmServerTx: vault.send unexpectedly returned dryRun result"
|
|
6467
|
+
);
|
|
6468
|
+
}
|
|
6469
|
+
this.pendingPayloads.clear();
|
|
6470
|
+
const broadcast = result;
|
|
6471
|
+
const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, broadcast.txHash);
|
|
6472
|
+
return {
|
|
6473
|
+
tx_hash: broadcast.txHash,
|
|
6474
|
+
chain: chain.toString(),
|
|
6475
|
+
status: "pending",
|
|
6476
|
+
explorer_url: explorerUrl
|
|
6477
|
+
};
|
|
6478
|
+
}
|
|
6479
|
+
/**
|
|
6480
|
+
* Sign and broadcast a THORChain / MayaChain MsgDeposit-style swap
|
|
6481
|
+
* envelope by reconstructing `vault.swap` args from the memo.
|
|
6482
|
+
*
|
|
6483
|
+
* The agent emits envelopes shaped:
|
|
6484
|
+
* { txArgs: { chain: 'THORChain', tx_encoding: 'cosmos-msg',
|
|
6485
|
+
* to: '', amount: '<base>', denom: 'rune',
|
|
6486
|
+
* memo: '=:DEST_CHAIN.DEST_ASSET:DEST_ADDR::v0:slippage_bps',
|
|
6487
|
+
* msg_type: 'deposit' } }
|
|
6488
|
+
*
|
|
6489
|
+
* The memo is THORChain's standard swap memo. We parse out the
|
|
6490
|
+
* destination chain + asset, look up the corresponding `Chain` enum,
|
|
6491
|
+
* then call `vault.swap` which builds the MsgDeposit internally.
|
|
6492
|
+
*
|
|
6493
|
+
* IMPORTANT — destination address handling: `vault.swap` re-derives the
|
|
6494
|
+
* destination address from `vault.address(toChain)` when fetching the
|
|
6495
|
+
* native swap quote (see `findSwapQuote` → `getNativeSwapQuote` —
|
|
6496
|
+
* `destination: to.address`). It does NOT honor the destination address
|
|
6497
|
+
* encoded in the envelope's memo. As a fund-safety guard we therefore
|
|
6498
|
+
* require the memo's destination address to match the vault's own
|
|
6499
|
+
* destination address (self-swap) and throw otherwise — see Phase D
|
|
6500
|
+
* review F1. Cross-account routing must wait on a Phase E SDK extension
|
|
6501
|
+
* that lets `vault.swap` accept a user-supplied destination.
|
|
6502
|
+
*/
|
|
6503
|
+
async signThorMsgDepositSwap(serverTxData, chain) {
|
|
6504
|
+
const txArgs = serverTxData?.txArgs ?? {};
|
|
6505
|
+
const memo = typeof txArgs.memo === "string" ? txArgs.memo : "";
|
|
6506
|
+
const parsed = parseThorSwapMemo(memo);
|
|
6507
|
+
const toChain = THOR_MEMO_CHAIN_TO_ENUM[parsed.destChainCode];
|
|
6508
|
+
if (!toChain) {
|
|
6509
|
+
throw new VaultError3(
|
|
6510
|
+
VaultErrorCode3.UnsupportedChain,
|
|
6511
|
+
`signThorMsgDepositSwap: unsupported destination chain code '${parsed.destChainCode}' in memo '${memo}'.`
|
|
6512
|
+
);
|
|
6513
|
+
}
|
|
6514
|
+
const vaultDestAddress = await this.vault.address(toChain);
|
|
6515
|
+
const normalizeForCompare = (addr) => EVM_CHAINS.has(toChain) ? addr.toLowerCase() : addr;
|
|
6516
|
+
if (parsed.destAddress && normalizeForCompare(parsed.destAddress) !== normalizeForCompare(vaultDestAddress)) {
|
|
6517
|
+
throw new VaultError3(
|
|
6518
|
+
VaultErrorCode3.NotImplemented,
|
|
6519
|
+
`signThorMsgDepositSwap: memo destination '${parsed.destAddress}' does not match vault address '${vaultDestAddress}' on ${toChain}. Phase D only supports self-swaps; cross-account routing requires a Phase E SDK extension that passes the user-supplied destination through to vault.swap.`
|
|
6520
|
+
);
|
|
6521
|
+
}
|
|
6522
|
+
const fromSymbol = chain === Chain10.THORChain ? "RUNE" : "CACAO";
|
|
6523
|
+
const amountRaw = typeof txArgs.amount === "string" ? txArgs.amount : void 0;
|
|
6524
|
+
if (!amountRaw) {
|
|
6525
|
+
throw new VaultError3(
|
|
6526
|
+
VaultErrorCode3.InvalidConfig,
|
|
6527
|
+
`signThorMsgDepositSwap: missing or non-string 'amount' field on ${chain} envelope`
|
|
6528
|
+
);
|
|
6529
|
+
}
|
|
6530
|
+
const amountDecimal = convertBaseUnitsToDecimal(chain, amountRaw, "signThorMsgDepositSwap");
|
|
6531
|
+
if (this.verbose)
|
|
6532
|
+
process.stderr.write(
|
|
6533
|
+
`[sign_thor_msg_deposit_swap] ${fromSymbol}@${chain} \u2192 ${parsed.destAsset}@${toChain}, amount=${amountDecimal}, memo='${memo}'
|
|
6534
|
+
`
|
|
6535
|
+
);
|
|
6536
|
+
const result = await this.vault.swap({
|
|
6537
|
+
fromChain: chain,
|
|
6538
|
+
fromSymbol,
|
|
6539
|
+
toChain,
|
|
6540
|
+
toSymbol: parsed.destAsset,
|
|
6541
|
+
amount: amountDecimal
|
|
6542
|
+
});
|
|
6543
|
+
if (result.dryRun) {
|
|
6544
|
+
throw new VaultError3(
|
|
6545
|
+
VaultErrorCode3.InvalidConfig,
|
|
6546
|
+
"signThorMsgDepositSwap: vault.swap unexpectedly returned dryRun result"
|
|
6547
|
+
);
|
|
6548
|
+
}
|
|
6549
|
+
this.pendingPayloads.clear();
|
|
6550
|
+
const broadcast = result;
|
|
6551
|
+
const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, broadcast.txHash);
|
|
6552
|
+
return {
|
|
6553
|
+
tx_hash: broadcast.txHash,
|
|
6554
|
+
chain: chain.toString(),
|
|
6555
|
+
status: "pending",
|
|
6556
|
+
explorer_url: explorerUrl
|
|
6557
|
+
};
|
|
6558
|
+
}
|
|
6559
|
+
/**
|
|
6560
|
+
* Sign and broadcast a THORChain / MayaChain MsgDeposit envelope whose
|
|
6561
|
+
* memo is an LP add (`+:POOL[:PAIRED]`) or remove (`-:POOL:BPS[:ASSET]`).
|
|
6562
|
+
*
|
|
6563
|
+
* The agent emits the same `cosmos-msg / msg_type: deposit` envelope as
|
|
6564
|
+
* the swap path; only the memo prefix differs. The memo is opaque
|
|
6565
|
+
* pass-through — sdk-cli doesn't parse pool / paired address / bps
|
|
6566
|
+
* because the SDK doesn't need to, the on-chain handler does.
|
|
6567
|
+
*
|
|
6568
|
+
* Uses `vault.signMsgDeposit` which builds a THORChainDeposit cosmos
|
|
6569
|
+
* message via the SDK's keysign payload pipeline. Amount is consumed
|
|
6570
|
+
* as base units directly (no decimal conversion) since the agent
|
|
6571
|
+
* already emits RUNE / CACAO in base units.
|
|
6572
|
+
*/
|
|
6573
|
+
async signThorMsgDepositLp(serverTxData, chain) {
|
|
6574
|
+
const txArgs = serverTxData?.txArgs ?? {};
|
|
6575
|
+
const memo = typeof txArgs.memo === "string" ? txArgs.memo : "";
|
|
6576
|
+
const amountRaw = typeof txArgs.amount === "string" ? txArgs.amount : void 0;
|
|
6577
|
+
if (!amountRaw) {
|
|
6578
|
+
throw new VaultError3(
|
|
6579
|
+
VaultErrorCode3.InvalidConfig,
|
|
6580
|
+
`signThorMsgDepositLp: missing or non-string 'amount' field on ${chain} envelope`
|
|
6581
|
+
);
|
|
6582
|
+
}
|
|
6583
|
+
if (amountRaw.length > MAX_AMOUNT_DIGITS) {
|
|
6584
|
+
throw new VaultError3(
|
|
6585
|
+
VaultErrorCode3.InvalidAmount,
|
|
6586
|
+
`signThorMsgDepositLp: amount '${amountRaw}' for ${chain} exceeds ${MAX_AMOUNT_DIGITS}-digit safety bound. Likely a quote-side bug. Refusing to sign.`
|
|
6587
|
+
);
|
|
6588
|
+
}
|
|
6589
|
+
if (this.verbose)
|
|
6590
|
+
process.stderr.write(`[sign_thor_msg_deposit_lp] chain=${chain}, memo='${memo}', amountBaseUnits=${amountRaw}
|
|
6591
|
+
`);
|
|
6592
|
+
const result = await this.vault.signMsgDeposit({ chain, amountBaseUnits: amountRaw, memo });
|
|
6593
|
+
this.pendingPayloads.clear();
|
|
6594
|
+
const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, result.txHash);
|
|
6595
|
+
return {
|
|
6596
|
+
tx_hash: result.txHash,
|
|
6597
|
+
chain: chain.toString(),
|
|
6598
|
+
status: "pending",
|
|
6599
|
+
explorer_url: explorerUrl
|
|
6600
|
+
};
|
|
6601
|
+
}
|
|
6602
|
+
/**
|
|
6603
|
+
* Sign and broadcast a server-built EVM transaction (raw EVM tx from
|
|
6604
|
+
* tx_ready SSE). Uses vault.prepareSendTx with memo field to carry the
|
|
6605
|
+
* calldata, plus EVM-specific nonce/lock plumbing that Phase B's
|
|
6606
|
+
* `signMultiLeg` depends on for back-to-back approve+main broadcasts.
|
|
6607
|
+
*/
|
|
6608
|
+
async signEvmServerTx(serverTxData, defaultChain, params) {
|
|
5897
6609
|
const swapTx = extractNestedTx(serverTxData);
|
|
5898
6610
|
if (!swapTx?.to) {
|
|
5899
6611
|
throw new Error("Server transaction missing required fields (to)");
|
|
@@ -5987,6 +6699,97 @@ var AgentExecutor = class {
|
|
|
5987
6699
|
throw err;
|
|
5988
6700
|
}
|
|
5989
6701
|
}
|
|
6702
|
+
/**
|
|
6703
|
+
* Sign and broadcast a 2-leg ERC-20 approve + main flow originating from
|
|
6704
|
+
* mcp-ts `execute_*` envelopes that carry both `approvalTxArgs` and
|
|
6705
|
+
* `txArgs`. Mirrors vultiagent's `useTransactionFlow`: leg 1 (approve) is
|
|
6706
|
+
* signed and broadcast first, the receipt is awaited, then leg 2 (main)
|
|
6707
|
+
* is signed and broadcast. Fails closed if the approve doesn't confirm
|
|
6708
|
+
* — the main leg is NEVER broadcast against a stale or failed allowance.
|
|
6709
|
+
*
|
|
6710
|
+
* Phase B is intentionally EVM-only; non-EVM 2-leg flows are not a real
|
|
6711
|
+
* shape on mcp-ts today (Pattern 1 / Pattern 2 multi-leg flows are split
|
|
6712
|
+
* server-side via sequence_id and don't traverse this path).
|
|
6713
|
+
*/
|
|
6714
|
+
async signMultiLeg(_payload, chain, params) {
|
|
6715
|
+
const [approveLeg, mainLeg] = this.pendingLegs;
|
|
6716
|
+
try {
|
|
6717
|
+
const approveEnvelope = {
|
|
6718
|
+
...approveLeg.parent,
|
|
6719
|
+
txArgs: approveLeg.txArgs,
|
|
6720
|
+
approvalTxArgs: void 0,
|
|
6721
|
+
__multiLeg: void 0,
|
|
6722
|
+
swap_tx: void 0,
|
|
6723
|
+
send_tx: void 0,
|
|
6724
|
+
tx: void 0
|
|
6725
|
+
};
|
|
6726
|
+
const approveResult = await this.signServerTx(approveEnvelope, chain, params);
|
|
6727
|
+
const approveTxHash = approveResult.tx_hash;
|
|
6728
|
+
if (!approveTxHash) {
|
|
6729
|
+
throw new VaultError3(VaultErrorCode3.BroadcastFailed, "signMultiLeg: approve leg returned no tx_hash");
|
|
6730
|
+
}
|
|
6731
|
+
if (this.verbose)
|
|
6732
|
+
process.stderr.write(`[signMultiLeg] approve broadcast: ${approveTxHash}, waiting for receipt...
|
|
6733
|
+
`);
|
|
6734
|
+
try {
|
|
6735
|
+
await this.waitForEvmReceipt(chain, approveTxHash, { timeoutSec: 90 });
|
|
6736
|
+
} catch (err) {
|
|
6737
|
+
throw new VaultError3(
|
|
6738
|
+
VaultErrorCode3.Timeout,
|
|
6739
|
+
`signMultiLeg: approve leg ${approveTxHash} did not confirm: ${err?.message ?? err}`,
|
|
6740
|
+
err instanceof Error ? err : void 0
|
|
6741
|
+
);
|
|
6742
|
+
}
|
|
6743
|
+
if (this.verbose) process.stderr.write(`[signMultiLeg] approve confirmed, broadcasting main leg
|
|
6744
|
+
`);
|
|
6745
|
+
const mainEnvelope = {
|
|
6746
|
+
...mainLeg.parent,
|
|
6747
|
+
txArgs: mainLeg.txArgs,
|
|
6748
|
+
approvalTxArgs: void 0,
|
|
6749
|
+
__multiLeg: void 0,
|
|
6750
|
+
swap_tx: void 0,
|
|
6751
|
+
send_tx: void 0,
|
|
6752
|
+
tx: void 0
|
|
6753
|
+
};
|
|
6754
|
+
const mainResult = await this.signServerTx(mainEnvelope, chain, params);
|
|
6755
|
+
return {
|
|
6756
|
+
tx_hash: mainResult.tx_hash,
|
|
6757
|
+
approval_tx_hash: approveTxHash,
|
|
6758
|
+
chain: mainResult.chain,
|
|
6759
|
+
status: "pending",
|
|
6760
|
+
explorer_url: mainResult.explorer_url
|
|
6761
|
+
};
|
|
6762
|
+
} finally {
|
|
6763
|
+
this.pendingLegs = [];
|
|
6764
|
+
}
|
|
6765
|
+
}
|
|
6766
|
+
/**
|
|
6767
|
+
* Poll vault.getTxStatus until the EVM tx confirms or the timeout fires.
|
|
6768
|
+
* Mirrors VaultBase's private `waitForConfirmation` (used by `vault.swap`
|
|
6769
|
+
* for its own approve-before-swap flow) — kept at the executor layer here
|
|
6770
|
+
* so we can stub it from unit tests without exposing private SDK methods.
|
|
6771
|
+
*
|
|
6772
|
+
* Throws on timeout or on receipt status === 'error' (revert). Returns on
|
|
6773
|
+
* success.
|
|
6774
|
+
*/
|
|
6775
|
+
async waitForEvmReceipt(chain, txHash, opts) {
|
|
6776
|
+
const intervalMs = 3e3;
|
|
6777
|
+
const deadline = Date.now() + opts.timeoutSec * 1e3;
|
|
6778
|
+
while (Date.now() < deadline) {
|
|
6779
|
+
try {
|
|
6780
|
+
const result = await this.vault.getTxStatus({ chain, txHash });
|
|
6781
|
+
if (result?.status === "success") return;
|
|
6782
|
+
if (result?.status === "error") {
|
|
6783
|
+
throw new VaultError3(VaultErrorCode3.BroadcastFailed, `approve tx reverted (${txHash})`);
|
|
6784
|
+
}
|
|
6785
|
+
} catch (e) {
|
|
6786
|
+
if (e instanceof VaultError3 && e.code === VaultErrorCode3.BroadcastFailed) throw e;
|
|
6787
|
+
if (e?.message?.includes("reverted")) throw e;
|
|
6788
|
+
}
|
|
6789
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
6790
|
+
}
|
|
6791
|
+
throw new VaultError3(VaultErrorCode3.Timeout, `approve tx ${txHash} not confirmed within ${opts.timeoutSec}s`);
|
|
6792
|
+
}
|
|
5990
6793
|
/**
|
|
5991
6794
|
* Build, sign, and broadcast a Solana swap locally using the SDK's swap flow.
|
|
5992
6795
|
* Uses swap params from the tx_ready event to call vault.getSwapQuote → prepareSwapTx.
|
|
@@ -6305,11 +7108,11 @@ var AgentExecutor = class {
|
|
|
6305
7108
|
`);
|
|
6306
7109
|
const chainName = params.chain;
|
|
6307
7110
|
const chainId = domain.chainId;
|
|
6308
|
-
let chain =
|
|
7111
|
+
let chain = Chain10.Ethereum;
|
|
6309
7112
|
if (chainName) {
|
|
6310
|
-
chain = resolveChain(chainName) ||
|
|
7113
|
+
chain = resolveChain(chainName) || Chain10.Ethereum;
|
|
6311
7114
|
} else if (chainId) {
|
|
6312
|
-
chain = resolveChainId(chainId) ||
|
|
7115
|
+
chain = resolveChainId(chainId) || Chain10.Ethereum;
|
|
6313
7116
|
}
|
|
6314
7117
|
const sigResult = await this.vault.signBytes({
|
|
6315
7118
|
data: eip712Hash,
|
|
@@ -6414,11 +7217,11 @@ var AgentExecutor = class {
|
|
|
6414
7217
|
};
|
|
6415
7218
|
function resolveChain(name) {
|
|
6416
7219
|
if (!name) return null;
|
|
6417
|
-
if (Object.values(
|
|
7220
|
+
if (Object.values(Chain10).includes(name)) {
|
|
6418
7221
|
return name;
|
|
6419
7222
|
}
|
|
6420
7223
|
const lower = name.toLowerCase();
|
|
6421
|
-
for (const [, value] of Object.entries(
|
|
7224
|
+
for (const [, value] of Object.entries(Chain10)) {
|
|
6422
7225
|
if (typeof value === "string" && value.toLowerCase() === lower) {
|
|
6423
7226
|
return value;
|
|
6424
7227
|
}
|
|
@@ -6444,7 +7247,7 @@ function resolveChain(name) {
|
|
|
6444
7247
|
xrp: "Ripple"
|
|
6445
7248
|
};
|
|
6446
7249
|
const aliased = aliases[lower];
|
|
6447
|
-
if (aliased && Object.values(
|
|
7250
|
+
if (aliased && Object.values(Chain10).includes(aliased)) {
|
|
6448
7251
|
return aliased;
|
|
6449
7252
|
}
|
|
6450
7253
|
return null;
|
|
@@ -6480,20 +7283,89 @@ function resolveChainFromTxReady(txReadyData) {
|
|
|
6480
7283
|
function extractNestedTx(txReadyData) {
|
|
6481
7284
|
return txReadyData?.swap_tx || txReadyData?.send_tx || txReadyData?.tx || txReadyData?.txArgs?.tx;
|
|
6482
7285
|
}
|
|
7286
|
+
var MAX_AMOUNT_DIGITS = 26;
|
|
7287
|
+
function convertBaseUnitsToDecimal(chain, amountRaw, context) {
|
|
7288
|
+
if (amountRaw.length > MAX_AMOUNT_DIGITS) {
|
|
7289
|
+
throw new VaultError3(
|
|
7290
|
+
VaultErrorCode3.InvalidAmount,
|
|
7291
|
+
`${context}: amount '${amountRaw}' for ${chain} exceeds ${MAX_AMOUNT_DIGITS}-digit safety bound. Likely a quote-side bug. Refusing to sign.`
|
|
7292
|
+
);
|
|
7293
|
+
}
|
|
7294
|
+
const decimals = chainFeeCoin[chain]?.decimals;
|
|
7295
|
+
if (decimals === void 0) {
|
|
7296
|
+
throw new VaultError3(VaultErrorCode3.UnsupportedChain, `${context}: no native decimals registered for ${chain}`);
|
|
7297
|
+
}
|
|
7298
|
+
try {
|
|
7299
|
+
return formatUnits(BigInt(amountRaw), decimals);
|
|
7300
|
+
} catch (err) {
|
|
7301
|
+
throw new VaultError3(
|
|
7302
|
+
VaultErrorCode3.InvalidAmount,
|
|
7303
|
+
`${context}: failed to convert amount '${amountRaw}' for ${chain}: ${err?.message ?? err}`
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
}
|
|
7307
|
+
function parseNonEvmEnvelope(serverTxData, chain) {
|
|
7308
|
+
const txArgs = serverTxData?.txArgs ?? serverTxData;
|
|
7309
|
+
if (!txArgs || typeof txArgs !== "object") {
|
|
7310
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, "parseNonEvmEnvelope: envelope missing txArgs");
|
|
7311
|
+
}
|
|
7312
|
+
const to = typeof txArgs.to === "string" ? txArgs.to : void 0;
|
|
7313
|
+
if (!to) {
|
|
7314
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, `parseNonEvmEnvelope: missing 'to' field for ${chain}`);
|
|
7315
|
+
}
|
|
7316
|
+
const amountRaw = typeof txArgs.amount === "string" ? txArgs.amount : void 0;
|
|
7317
|
+
if (!amountRaw) {
|
|
7318
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, `parseNonEvmEnvelope: missing 'amount' field for ${chain}`);
|
|
7319
|
+
}
|
|
7320
|
+
const amountDecimal = convertBaseUnitsToDecimal(chain, amountRaw, "parseNonEvmEnvelope");
|
|
7321
|
+
let symbol;
|
|
7322
|
+
const tokenResolved = serverTxData?.resolved?.labels?.token_resolved;
|
|
7323
|
+
const nativeTicker = chainFeeCoin[chain]?.ticker;
|
|
7324
|
+
if (typeof tokenResolved === "string" && tokenResolved !== nativeTicker) {
|
|
7325
|
+
symbol = tokenResolved;
|
|
7326
|
+
}
|
|
7327
|
+
const memo = typeof txArgs.memo === "string" && txArgs.memo.length > 0 ? txArgs.memo : void 0;
|
|
7328
|
+
return { chain, to, amount: amountDecimal, symbol, memo };
|
|
7329
|
+
}
|
|
7330
|
+
function parseThorSwapMemo(memo) {
|
|
7331
|
+
if (!memo.startsWith("=:")) {
|
|
7332
|
+
throw new VaultError3(
|
|
7333
|
+
VaultErrorCode3.NotImplemented,
|
|
7334
|
+
`parseThorSwapMemo: only swap memos (=:CHAIN.ASSET:DEST...) supported on this path; got memo='${memo}'. LP memos (+:/-:) route through signThorMsgDepositLp; loan / validator ops out of scope.`
|
|
7335
|
+
);
|
|
7336
|
+
}
|
|
7337
|
+
const memoBody = memo.slice(2);
|
|
7338
|
+
const parts = memoBody.split(":");
|
|
7339
|
+
let chainAsset = parts[0];
|
|
7340
|
+
if (chainAsset && !chainAsset.includes(".")) {
|
|
7341
|
+
const expanded = THOR_MEMO_ASSET_SHORTCUTS[chainAsset.toLowerCase()];
|
|
7342
|
+
if (expanded) chainAsset = expanded;
|
|
7343
|
+
}
|
|
7344
|
+
if (!chainAsset || !chainAsset.includes(".")) {
|
|
7345
|
+
throw new VaultError3(
|
|
7346
|
+
VaultErrorCode3.InvalidConfig,
|
|
7347
|
+
`parseThorSwapMemo: malformed swap memo '${memo}': missing CHAIN.ASSET in first segment.`
|
|
7348
|
+
);
|
|
7349
|
+
}
|
|
7350
|
+
const [destChainCode, destAssetRaw] = chainAsset.split(".");
|
|
7351
|
+
const destAsset = destAssetRaw?.split("-")[0] ?? "";
|
|
7352
|
+
const destAddress = typeof parts[1] === "string" ? parts[1] : "";
|
|
7353
|
+
return { destChainCode, destAsset, destAddress };
|
|
7354
|
+
}
|
|
6483
7355
|
function resolveChainId(chainId) {
|
|
6484
7356
|
const id = typeof chainId === "string" ? parseInt(chainId, 10) : chainId;
|
|
6485
7357
|
if (isNaN(id)) return null;
|
|
6486
7358
|
const chainIdMap = {
|
|
6487
|
-
1:
|
|
6488
|
-
56:
|
|
6489
|
-
137:
|
|
6490
|
-
43114:
|
|
6491
|
-
42161:
|
|
6492
|
-
10:
|
|
6493
|
-
8453:
|
|
6494
|
-
81457:
|
|
6495
|
-
324:
|
|
6496
|
-
25:
|
|
7359
|
+
1: Chain10.Ethereum,
|
|
7360
|
+
56: Chain10.BSC,
|
|
7361
|
+
137: Chain10.Polygon,
|
|
7362
|
+
43114: Chain10.Avalanche,
|
|
7363
|
+
42161: Chain10.Arbitrum,
|
|
7364
|
+
10: Chain10.Optimism,
|
|
7365
|
+
8453: Chain10.Base,
|
|
7366
|
+
81457: Chain10.Blast,
|
|
7367
|
+
324: Chain10.Zksync,
|
|
7368
|
+
25: Chain10.CronosChain
|
|
6497
7369
|
};
|
|
6498
7370
|
return chainIdMap[id] || null;
|
|
6499
7371
|
}
|
|
@@ -7858,7 +8730,7 @@ var cachedVersion = null;
|
|
|
7858
8730
|
function getVersion() {
|
|
7859
8731
|
if (cachedVersion) return cachedVersion;
|
|
7860
8732
|
if (true) {
|
|
7861
|
-
cachedVersion = "0.
|
|
8733
|
+
cachedVersion = "0.23.0";
|
|
7862
8734
|
return cachedVersion;
|
|
7863
8735
|
}
|
|
7864
8736
|
try {
|
|
@@ -8141,7 +9013,7 @@ function readArgValue(args, optionName) {
|
|
|
8141
9013
|
}
|
|
8142
9014
|
|
|
8143
9015
|
// src/interactive/completer.ts
|
|
8144
|
-
import { Chain as
|
|
9016
|
+
import { Chain as Chain11 } from "@vultisig/sdk";
|
|
8145
9017
|
import fs3 from "fs";
|
|
8146
9018
|
import path3 from "path";
|
|
8147
9019
|
var COMMANDS = [
|
|
@@ -8285,7 +9157,7 @@ function completeVaultName(ctx2, partial) {
|
|
|
8285
9157
|
return [show, partial];
|
|
8286
9158
|
}
|
|
8287
9159
|
function completeChainName(partial) {
|
|
8288
|
-
const allChains = Object.values(
|
|
9160
|
+
const allChains = Object.values(Chain11);
|
|
8289
9161
|
const partialLower = partial.toLowerCase();
|
|
8290
9162
|
const matches = allChains.filter((chain) => chain.toLowerCase().startsWith(partialLower));
|
|
8291
9163
|
matches.sort();
|
|
@@ -8293,7 +9165,7 @@ function completeChainName(partial) {
|
|
|
8293
9165
|
return [show, partial];
|
|
8294
9166
|
}
|
|
8295
9167
|
function findChainByName(name) {
|
|
8296
|
-
const allChains = Object.values(
|
|
9168
|
+
const allChains = Object.values(Chain11);
|
|
8297
9169
|
const nameLower = name.toLowerCase();
|
|
8298
9170
|
const found = allChains.find((chain) => chain.toLowerCase() === nameLower);
|
|
8299
9171
|
return found ? found : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "The self-custody MPC wallet CLI for AI coding agents (Claude Code, Cursor, OpenCode). Natural-language agent mode, 36+ chains, DKLS23 threshold signatures. Seedless.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
"@cosmjs/stargate": "^0.38.1",
|
|
74
74
|
"@napi-rs/keyring": "^1.3.0",
|
|
75
75
|
"@noble/hashes": "^2.0.1",
|
|
76
|
-
"@vultisig/client-shared": "^0.2.
|
|
77
|
-
"@vultisig/core-chain": "^1.
|
|
78
|
-
"@vultisig/rujira": "^
|
|
79
|
-
"@vultisig/sdk": "^0.
|
|
76
|
+
"@vultisig/client-shared": "^0.2.7",
|
|
77
|
+
"@vultisig/core-chain": "^1.7.1",
|
|
78
|
+
"@vultisig/rujira": "^18.0.0",
|
|
79
|
+
"@vultisig/sdk": "^0.23.0",
|
|
80
80
|
"chalk": "^5.6.2",
|
|
81
81
|
"cli-table3": "^0.6.5",
|
|
82
82
|
"commander": "^14.0.3",
|