@vultisig/cli 0.22.5 → 0.22.7
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 +10 -0
- package/dist/index.js +850 -31
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 0.22.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#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.
|
|
8
|
+
|
|
9
|
+
- 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)]:
|
|
10
|
+
- @vultisig/sdk@0.22.7
|
|
11
|
+
- @vultisig/core-chain@1.7.1
|
|
12
|
+
|
|
3
13
|
## 0.22.5
|
|
4
14
|
|
|
5
15
|
### 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,170 @@ 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
|
+
return this.signThorMsgDepositSwap(serverTxData, chain);
|
|
6439
|
+
}
|
|
6440
|
+
const args = parseNonEvmEnvelope(serverTxData, chain);
|
|
6441
|
+
if (this.verbose)
|
|
6442
|
+
process.stderr.write(
|
|
6443
|
+
`[sign_non_evm_server_tx] chain=${chain}, to=${args.to}, amount=${args.amount}${args.symbol ? ` ${args.symbol}` : ""}, memo=${args.memo ? `"${args.memo}"` : "(none)"}
|
|
6444
|
+
`
|
|
6445
|
+
);
|
|
6446
|
+
const result = await this.vault.send({
|
|
6447
|
+
chain,
|
|
6448
|
+
to: args.to,
|
|
6449
|
+
amount: args.amount,
|
|
6450
|
+
symbol: args.symbol,
|
|
6451
|
+
memo: args.memo
|
|
6452
|
+
});
|
|
6453
|
+
if (result.dryRun) {
|
|
6454
|
+
throw new VaultError3(
|
|
6455
|
+
VaultErrorCode3.InvalidConfig,
|
|
6456
|
+
"signNonEvmServerTx: vault.send unexpectedly returned dryRun result"
|
|
6457
|
+
);
|
|
6458
|
+
}
|
|
6459
|
+
this.pendingPayloads.clear();
|
|
6460
|
+
const broadcast = result;
|
|
6461
|
+
const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, broadcast.txHash);
|
|
6462
|
+
return {
|
|
6463
|
+
tx_hash: broadcast.txHash,
|
|
6464
|
+
chain: chain.toString(),
|
|
6465
|
+
status: "pending",
|
|
6466
|
+
explorer_url: explorerUrl
|
|
6467
|
+
};
|
|
6468
|
+
}
|
|
6469
|
+
/**
|
|
6470
|
+
* Sign and broadcast a THORChain / MayaChain MsgDeposit-style swap
|
|
6471
|
+
* envelope by reconstructing `vault.swap` args from the memo.
|
|
6472
|
+
*
|
|
6473
|
+
* The agent emits envelopes shaped:
|
|
6474
|
+
* { txArgs: { chain: 'THORChain', tx_encoding: 'cosmos-msg',
|
|
6475
|
+
* to: '', amount: '<base>', denom: 'rune',
|
|
6476
|
+
* memo: '=:DEST_CHAIN.DEST_ASSET:DEST_ADDR::v0:slippage_bps',
|
|
6477
|
+
* msg_type: 'deposit' } }
|
|
6478
|
+
*
|
|
6479
|
+
* The memo is THORChain's standard swap memo. We parse out the
|
|
6480
|
+
* destination chain + asset, look up the corresponding `Chain` enum,
|
|
6481
|
+
* then call `vault.swap` which builds the MsgDeposit internally.
|
|
6482
|
+
*
|
|
6483
|
+
* IMPORTANT — destination address handling: `vault.swap` re-derives the
|
|
6484
|
+
* destination address from `vault.address(toChain)` when fetching the
|
|
6485
|
+
* native swap quote (see `findSwapQuote` → `getNativeSwapQuote` —
|
|
6486
|
+
* `destination: to.address`). It does NOT honor the destination address
|
|
6487
|
+
* encoded in the envelope's memo. As a fund-safety guard we therefore
|
|
6488
|
+
* require the memo's destination address to match the vault's own
|
|
6489
|
+
* destination address (self-swap) and throw otherwise — see Phase D
|
|
6490
|
+
* review F1. Cross-account routing must wait on a Phase E SDK extension
|
|
6491
|
+
* that lets `vault.swap` accept a user-supplied destination.
|
|
6492
|
+
*/
|
|
6493
|
+
async signThorMsgDepositSwap(serverTxData, chain) {
|
|
6494
|
+
const txArgs = serverTxData?.txArgs ?? {};
|
|
6495
|
+
const memo = typeof txArgs.memo === "string" ? txArgs.memo : "";
|
|
6496
|
+
const parsed = parseThorSwapMemo(memo);
|
|
6497
|
+
const toChain = THOR_MEMO_CHAIN_TO_ENUM[parsed.destChainCode];
|
|
6498
|
+
if (!toChain) {
|
|
6499
|
+
throw new VaultError3(
|
|
6500
|
+
VaultErrorCode3.UnsupportedChain,
|
|
6501
|
+
`signThorMsgDepositSwap: unsupported destination chain code '${parsed.destChainCode}' in memo '${memo}'.`
|
|
6502
|
+
);
|
|
6503
|
+
}
|
|
6504
|
+
const vaultDestAddress = await this.vault.address(toChain);
|
|
6505
|
+
const normalizeForCompare = (addr) => EVM_CHAINS.has(toChain) ? addr.toLowerCase() : addr;
|
|
6506
|
+
if (parsed.destAddress && normalizeForCompare(parsed.destAddress) !== normalizeForCompare(vaultDestAddress)) {
|
|
6507
|
+
throw new VaultError3(
|
|
6508
|
+
VaultErrorCode3.NotImplemented,
|
|
6509
|
+
`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.`
|
|
6510
|
+
);
|
|
6511
|
+
}
|
|
6512
|
+
const fromSymbol = chain === Chain10.THORChain ? "RUNE" : "CACAO";
|
|
6513
|
+
const amountRaw = typeof txArgs.amount === "string" ? txArgs.amount : void 0;
|
|
6514
|
+
if (!amountRaw) {
|
|
6515
|
+
throw new VaultError3(
|
|
6516
|
+
VaultErrorCode3.InvalidConfig,
|
|
6517
|
+
`signThorMsgDepositSwap: missing or non-string 'amount' field on ${chain} envelope`
|
|
6518
|
+
);
|
|
6519
|
+
}
|
|
6520
|
+
const amountDecimal = convertBaseUnitsToDecimal(chain, amountRaw, "signThorMsgDepositSwap");
|
|
6521
|
+
if (this.verbose)
|
|
6522
|
+
process.stderr.write(
|
|
6523
|
+
`[sign_thor_msg_deposit_swap] ${fromSymbol}@${chain} \u2192 ${parsed.destAsset}@${toChain}, amount=${amountDecimal}, memo='${memo}'
|
|
6524
|
+
`
|
|
6525
|
+
);
|
|
6526
|
+
const result = await this.vault.swap({
|
|
6527
|
+
fromChain: chain,
|
|
6528
|
+
fromSymbol,
|
|
6529
|
+
toChain,
|
|
6530
|
+
toSymbol: parsed.destAsset,
|
|
6531
|
+
amount: amountDecimal
|
|
6532
|
+
});
|
|
6533
|
+
if (result.dryRun) {
|
|
6534
|
+
throw new VaultError3(
|
|
6535
|
+
VaultErrorCode3.InvalidConfig,
|
|
6536
|
+
"signThorMsgDepositSwap: vault.swap unexpectedly returned dryRun result"
|
|
6537
|
+
);
|
|
6538
|
+
}
|
|
6539
|
+
this.pendingPayloads.clear();
|
|
6540
|
+
const broadcast = result;
|
|
6541
|
+
const explorerUrl = VultisigSdk.getTxExplorerUrl(chain, broadcast.txHash);
|
|
6542
|
+
return {
|
|
6543
|
+
tx_hash: broadcast.txHash,
|
|
6544
|
+
chain: chain.toString(),
|
|
6545
|
+
status: "pending",
|
|
6546
|
+
explorer_url: explorerUrl
|
|
6547
|
+
};
|
|
6548
|
+
}
|
|
6549
|
+
/**
|
|
6550
|
+
* Sign and broadcast a server-built EVM transaction (raw EVM tx from
|
|
6551
|
+
* tx_ready SSE). Uses vault.prepareSendTx with memo field to carry the
|
|
6552
|
+
* calldata, plus EVM-specific nonce/lock plumbing that Phase B's
|
|
6553
|
+
* `signMultiLeg` depends on for back-to-back approve+main broadcasts.
|
|
6554
|
+
*/
|
|
6555
|
+
async signEvmServerTx(serverTxData, defaultChain, params) {
|
|
5897
6556
|
const swapTx = extractNestedTx(serverTxData);
|
|
5898
6557
|
if (!swapTx?.to) {
|
|
5899
6558
|
throw new Error("Server transaction missing required fields (to)");
|
|
@@ -5987,6 +6646,97 @@ var AgentExecutor = class {
|
|
|
5987
6646
|
throw err;
|
|
5988
6647
|
}
|
|
5989
6648
|
}
|
|
6649
|
+
/**
|
|
6650
|
+
* Sign and broadcast a 2-leg ERC-20 approve + main flow originating from
|
|
6651
|
+
* mcp-ts `execute_*` envelopes that carry both `approvalTxArgs` and
|
|
6652
|
+
* `txArgs`. Mirrors vultiagent's `useTransactionFlow`: leg 1 (approve) is
|
|
6653
|
+
* signed and broadcast first, the receipt is awaited, then leg 2 (main)
|
|
6654
|
+
* is signed and broadcast. Fails closed if the approve doesn't confirm
|
|
6655
|
+
* — the main leg is NEVER broadcast against a stale or failed allowance.
|
|
6656
|
+
*
|
|
6657
|
+
* Phase B is intentionally EVM-only; non-EVM 2-leg flows are not a real
|
|
6658
|
+
* shape on mcp-ts today (Pattern 1 / Pattern 2 multi-leg flows are split
|
|
6659
|
+
* server-side via sequence_id and don't traverse this path).
|
|
6660
|
+
*/
|
|
6661
|
+
async signMultiLeg(_payload, chain, params) {
|
|
6662
|
+
const [approveLeg, mainLeg] = this.pendingLegs;
|
|
6663
|
+
try {
|
|
6664
|
+
const approveEnvelope = {
|
|
6665
|
+
...approveLeg.parent,
|
|
6666
|
+
txArgs: approveLeg.txArgs,
|
|
6667
|
+
approvalTxArgs: void 0,
|
|
6668
|
+
__multiLeg: void 0,
|
|
6669
|
+
swap_tx: void 0,
|
|
6670
|
+
send_tx: void 0,
|
|
6671
|
+
tx: void 0
|
|
6672
|
+
};
|
|
6673
|
+
const approveResult = await this.signServerTx(approveEnvelope, chain, params);
|
|
6674
|
+
const approveTxHash = approveResult.tx_hash;
|
|
6675
|
+
if (!approveTxHash) {
|
|
6676
|
+
throw new VaultError3(VaultErrorCode3.BroadcastFailed, "signMultiLeg: approve leg returned no tx_hash");
|
|
6677
|
+
}
|
|
6678
|
+
if (this.verbose)
|
|
6679
|
+
process.stderr.write(`[signMultiLeg] approve broadcast: ${approveTxHash}, waiting for receipt...
|
|
6680
|
+
`);
|
|
6681
|
+
try {
|
|
6682
|
+
await this.waitForEvmReceipt(chain, approveTxHash, { timeoutSec: 90 });
|
|
6683
|
+
} catch (err) {
|
|
6684
|
+
throw new VaultError3(
|
|
6685
|
+
VaultErrorCode3.Timeout,
|
|
6686
|
+
`signMultiLeg: approve leg ${approveTxHash} did not confirm: ${err?.message ?? err}`,
|
|
6687
|
+
err instanceof Error ? err : void 0
|
|
6688
|
+
);
|
|
6689
|
+
}
|
|
6690
|
+
if (this.verbose) process.stderr.write(`[signMultiLeg] approve confirmed, broadcasting main leg
|
|
6691
|
+
`);
|
|
6692
|
+
const mainEnvelope = {
|
|
6693
|
+
...mainLeg.parent,
|
|
6694
|
+
txArgs: mainLeg.txArgs,
|
|
6695
|
+
approvalTxArgs: void 0,
|
|
6696
|
+
__multiLeg: void 0,
|
|
6697
|
+
swap_tx: void 0,
|
|
6698
|
+
send_tx: void 0,
|
|
6699
|
+
tx: void 0
|
|
6700
|
+
};
|
|
6701
|
+
const mainResult = await this.signServerTx(mainEnvelope, chain, params);
|
|
6702
|
+
return {
|
|
6703
|
+
tx_hash: mainResult.tx_hash,
|
|
6704
|
+
approval_tx_hash: approveTxHash,
|
|
6705
|
+
chain: mainResult.chain,
|
|
6706
|
+
status: "pending",
|
|
6707
|
+
explorer_url: mainResult.explorer_url
|
|
6708
|
+
};
|
|
6709
|
+
} finally {
|
|
6710
|
+
this.pendingLegs = [];
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
/**
|
|
6714
|
+
* Poll vault.getTxStatus until the EVM tx confirms or the timeout fires.
|
|
6715
|
+
* Mirrors VaultBase's private `waitForConfirmation` (used by `vault.swap`
|
|
6716
|
+
* for its own approve-before-swap flow) — kept at the executor layer here
|
|
6717
|
+
* so we can stub it from unit tests without exposing private SDK methods.
|
|
6718
|
+
*
|
|
6719
|
+
* Throws on timeout or on receipt status === 'error' (revert). Returns on
|
|
6720
|
+
* success.
|
|
6721
|
+
*/
|
|
6722
|
+
async waitForEvmReceipt(chain, txHash, opts) {
|
|
6723
|
+
const intervalMs = 3e3;
|
|
6724
|
+
const deadline = Date.now() + opts.timeoutSec * 1e3;
|
|
6725
|
+
while (Date.now() < deadline) {
|
|
6726
|
+
try {
|
|
6727
|
+
const result = await this.vault.getTxStatus({ chain, txHash });
|
|
6728
|
+
if (result?.status === "success") return;
|
|
6729
|
+
if (result?.status === "error") {
|
|
6730
|
+
throw new VaultError3(VaultErrorCode3.BroadcastFailed, `approve tx reverted (${txHash})`);
|
|
6731
|
+
}
|
|
6732
|
+
} catch (e) {
|
|
6733
|
+
if (e instanceof VaultError3 && e.code === VaultErrorCode3.BroadcastFailed) throw e;
|
|
6734
|
+
if (e?.message?.includes("reverted")) throw e;
|
|
6735
|
+
}
|
|
6736
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
6737
|
+
}
|
|
6738
|
+
throw new VaultError3(VaultErrorCode3.Timeout, `approve tx ${txHash} not confirmed within ${opts.timeoutSec}s`);
|
|
6739
|
+
}
|
|
5990
6740
|
/**
|
|
5991
6741
|
* Build, sign, and broadcast a Solana swap locally using the SDK's swap flow.
|
|
5992
6742
|
* Uses swap params from the tx_ready event to call vault.getSwapQuote → prepareSwapTx.
|
|
@@ -6305,11 +7055,11 @@ var AgentExecutor = class {
|
|
|
6305
7055
|
`);
|
|
6306
7056
|
const chainName = params.chain;
|
|
6307
7057
|
const chainId = domain.chainId;
|
|
6308
|
-
let chain =
|
|
7058
|
+
let chain = Chain10.Ethereum;
|
|
6309
7059
|
if (chainName) {
|
|
6310
|
-
chain = resolveChain(chainName) ||
|
|
7060
|
+
chain = resolveChain(chainName) || Chain10.Ethereum;
|
|
6311
7061
|
} else if (chainId) {
|
|
6312
|
-
chain = resolveChainId(chainId) ||
|
|
7062
|
+
chain = resolveChainId(chainId) || Chain10.Ethereum;
|
|
6313
7063
|
}
|
|
6314
7064
|
const sigResult = await this.vault.signBytes({
|
|
6315
7065
|
data: eip712Hash,
|
|
@@ -6414,11 +7164,11 @@ var AgentExecutor = class {
|
|
|
6414
7164
|
};
|
|
6415
7165
|
function resolveChain(name) {
|
|
6416
7166
|
if (!name) return null;
|
|
6417
|
-
if (Object.values(
|
|
7167
|
+
if (Object.values(Chain10).includes(name)) {
|
|
6418
7168
|
return name;
|
|
6419
7169
|
}
|
|
6420
7170
|
const lower = name.toLowerCase();
|
|
6421
|
-
for (const [, value] of Object.entries(
|
|
7171
|
+
for (const [, value] of Object.entries(Chain10)) {
|
|
6422
7172
|
if (typeof value === "string" && value.toLowerCase() === lower) {
|
|
6423
7173
|
return value;
|
|
6424
7174
|
}
|
|
@@ -6444,7 +7194,7 @@ function resolveChain(name) {
|
|
|
6444
7194
|
xrp: "Ripple"
|
|
6445
7195
|
};
|
|
6446
7196
|
const aliased = aliases[lower];
|
|
6447
|
-
if (aliased && Object.values(
|
|
7197
|
+
if (aliased && Object.values(Chain10).includes(aliased)) {
|
|
6448
7198
|
return aliased;
|
|
6449
7199
|
}
|
|
6450
7200
|
return null;
|
|
@@ -6480,20 +7230,89 @@ function resolveChainFromTxReady(txReadyData) {
|
|
|
6480
7230
|
function extractNestedTx(txReadyData) {
|
|
6481
7231
|
return txReadyData?.swap_tx || txReadyData?.send_tx || txReadyData?.tx || txReadyData?.txArgs?.tx;
|
|
6482
7232
|
}
|
|
7233
|
+
var MAX_AMOUNT_DIGITS = 26;
|
|
7234
|
+
function convertBaseUnitsToDecimal(chain, amountRaw, context) {
|
|
7235
|
+
if (amountRaw.length > MAX_AMOUNT_DIGITS) {
|
|
7236
|
+
throw new VaultError3(
|
|
7237
|
+
VaultErrorCode3.InvalidAmount,
|
|
7238
|
+
`${context}: amount '${amountRaw}' for ${chain} exceeds ${MAX_AMOUNT_DIGITS}-digit safety bound. Likely a quote-side bug. Refusing to sign.`
|
|
7239
|
+
);
|
|
7240
|
+
}
|
|
7241
|
+
const decimals = chainFeeCoin[chain]?.decimals;
|
|
7242
|
+
if (decimals === void 0) {
|
|
7243
|
+
throw new VaultError3(VaultErrorCode3.UnsupportedChain, `${context}: no native decimals registered for ${chain}`);
|
|
7244
|
+
}
|
|
7245
|
+
try {
|
|
7246
|
+
return formatUnits(BigInt(amountRaw), decimals);
|
|
7247
|
+
} catch (err) {
|
|
7248
|
+
throw new VaultError3(
|
|
7249
|
+
VaultErrorCode3.InvalidAmount,
|
|
7250
|
+
`${context}: failed to convert amount '${amountRaw}' for ${chain}: ${err?.message ?? err}`
|
|
7251
|
+
);
|
|
7252
|
+
}
|
|
7253
|
+
}
|
|
7254
|
+
function parseNonEvmEnvelope(serverTxData, chain) {
|
|
7255
|
+
const txArgs = serverTxData?.txArgs ?? serverTxData;
|
|
7256
|
+
if (!txArgs || typeof txArgs !== "object") {
|
|
7257
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, "parseNonEvmEnvelope: envelope missing txArgs");
|
|
7258
|
+
}
|
|
7259
|
+
const to = typeof txArgs.to === "string" ? txArgs.to : void 0;
|
|
7260
|
+
if (!to) {
|
|
7261
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, `parseNonEvmEnvelope: missing 'to' field for ${chain}`);
|
|
7262
|
+
}
|
|
7263
|
+
const amountRaw = typeof txArgs.amount === "string" ? txArgs.amount : void 0;
|
|
7264
|
+
if (!amountRaw) {
|
|
7265
|
+
throw new VaultError3(VaultErrorCode3.InvalidConfig, `parseNonEvmEnvelope: missing 'amount' field for ${chain}`);
|
|
7266
|
+
}
|
|
7267
|
+
const amountDecimal = convertBaseUnitsToDecimal(chain, amountRaw, "parseNonEvmEnvelope");
|
|
7268
|
+
let symbol;
|
|
7269
|
+
const tokenResolved = serverTxData?.resolved?.labels?.token_resolved;
|
|
7270
|
+
const nativeTicker = chainFeeCoin[chain]?.ticker;
|
|
7271
|
+
if (typeof tokenResolved === "string" && tokenResolved !== nativeTicker) {
|
|
7272
|
+
symbol = tokenResolved;
|
|
7273
|
+
}
|
|
7274
|
+
const memo = typeof txArgs.memo === "string" && txArgs.memo.length > 0 ? txArgs.memo : void 0;
|
|
7275
|
+
return { chain, to, amount: amountDecimal, symbol, memo };
|
|
7276
|
+
}
|
|
7277
|
+
function parseThorSwapMemo(memo) {
|
|
7278
|
+
if (!memo.startsWith("=:")) {
|
|
7279
|
+
throw new VaultError3(
|
|
7280
|
+
VaultErrorCode3.NotImplemented,
|
|
7281
|
+
`parseThorSwapMemo: only swap memos (=:CHAIN.ASSET:DEST...) supported on this path; got memo='${memo}'. LP / non-swap MsgDeposit flows route through different SDK helpers (Phase E follow-up).`
|
|
7282
|
+
);
|
|
7283
|
+
}
|
|
7284
|
+
const memoBody = memo.slice(2);
|
|
7285
|
+
const parts = memoBody.split(":");
|
|
7286
|
+
let chainAsset = parts[0];
|
|
7287
|
+
if (chainAsset && !chainAsset.includes(".")) {
|
|
7288
|
+
const expanded = THOR_MEMO_ASSET_SHORTCUTS[chainAsset.toLowerCase()];
|
|
7289
|
+
if (expanded) chainAsset = expanded;
|
|
7290
|
+
}
|
|
7291
|
+
if (!chainAsset || !chainAsset.includes(".")) {
|
|
7292
|
+
throw new VaultError3(
|
|
7293
|
+
VaultErrorCode3.InvalidConfig,
|
|
7294
|
+
`parseThorSwapMemo: malformed swap memo '${memo}': missing CHAIN.ASSET in first segment.`
|
|
7295
|
+
);
|
|
7296
|
+
}
|
|
7297
|
+
const [destChainCode, destAssetRaw] = chainAsset.split(".");
|
|
7298
|
+
const destAsset = destAssetRaw?.split("-")[0] ?? "";
|
|
7299
|
+
const destAddress = typeof parts[1] === "string" ? parts[1] : "";
|
|
7300
|
+
return { destChainCode, destAsset, destAddress };
|
|
7301
|
+
}
|
|
6483
7302
|
function resolveChainId(chainId) {
|
|
6484
7303
|
const id = typeof chainId === "string" ? parseInt(chainId, 10) : chainId;
|
|
6485
7304
|
if (isNaN(id)) return null;
|
|
6486
7305
|
const chainIdMap = {
|
|
6487
|
-
1:
|
|
6488
|
-
56:
|
|
6489
|
-
137:
|
|
6490
|
-
43114:
|
|
6491
|
-
42161:
|
|
6492
|
-
10:
|
|
6493
|
-
8453:
|
|
6494
|
-
81457:
|
|
6495
|
-
324:
|
|
6496
|
-
25:
|
|
7306
|
+
1: Chain10.Ethereum,
|
|
7307
|
+
56: Chain10.BSC,
|
|
7308
|
+
137: Chain10.Polygon,
|
|
7309
|
+
43114: Chain10.Avalanche,
|
|
7310
|
+
42161: Chain10.Arbitrum,
|
|
7311
|
+
10: Chain10.Optimism,
|
|
7312
|
+
8453: Chain10.Base,
|
|
7313
|
+
81457: Chain10.Blast,
|
|
7314
|
+
324: Chain10.Zksync,
|
|
7315
|
+
25: Chain10.CronosChain
|
|
6497
7316
|
};
|
|
6498
7317
|
return chainIdMap[id] || null;
|
|
6499
7318
|
}
|
|
@@ -7858,7 +8677,7 @@ var cachedVersion = null;
|
|
|
7858
8677
|
function getVersion() {
|
|
7859
8678
|
if (cachedVersion) return cachedVersion;
|
|
7860
8679
|
if (true) {
|
|
7861
|
-
cachedVersion = "0.22.
|
|
8680
|
+
cachedVersion = "0.22.7";
|
|
7862
8681
|
return cachedVersion;
|
|
7863
8682
|
}
|
|
7864
8683
|
try {
|
|
@@ -8141,7 +8960,7 @@ function readArgValue(args, optionName) {
|
|
|
8141
8960
|
}
|
|
8142
8961
|
|
|
8143
8962
|
// src/interactive/completer.ts
|
|
8144
|
-
import { Chain as
|
|
8963
|
+
import { Chain as Chain11 } from "@vultisig/sdk";
|
|
8145
8964
|
import fs3 from "fs";
|
|
8146
8965
|
import path3 from "path";
|
|
8147
8966
|
var COMMANDS = [
|
|
@@ -8285,7 +9104,7 @@ function completeVaultName(ctx2, partial) {
|
|
|
8285
9104
|
return [show, partial];
|
|
8286
9105
|
}
|
|
8287
9106
|
function completeChainName(partial) {
|
|
8288
|
-
const allChains = Object.values(
|
|
9107
|
+
const allChains = Object.values(Chain11);
|
|
8289
9108
|
const partialLower = partial.toLowerCase();
|
|
8290
9109
|
const matches = allChains.filter((chain) => chain.toLowerCase().startsWith(partialLower));
|
|
8291
9110
|
matches.sort();
|
|
@@ -8293,7 +9112,7 @@ function completeChainName(partial) {
|
|
|
8293
9112
|
return [show, partial];
|
|
8294
9113
|
}
|
|
8295
9114
|
function findChainByName(name) {
|
|
8296
|
-
const allChains = Object.values(
|
|
9115
|
+
const allChains = Object.values(Chain11);
|
|
8297
9116
|
const nameLower = name.toLowerCase();
|
|
8298
9117
|
const found = allChains.find((chain) => chain.toLowerCase() === nameLower);
|
|
8299
9118
|
return found ? found : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.7",
|
|
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": {
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@napi-rs/keyring": "^1.3.0",
|
|
75
75
|
"@noble/hashes": "^2.0.1",
|
|
76
76
|
"@vultisig/client-shared": "^0.2.6",
|
|
77
|
-
"@vultisig/core-chain": "^1.
|
|
77
|
+
"@vultisig/core-chain": "^1.7.1",
|
|
78
78
|
"@vultisig/rujira": "^17.0.1",
|
|
79
|
-
"@vultisig/sdk": "^0.22.
|
|
79
|
+
"@vultisig/sdk": "^0.22.7",
|
|
80
80
|
"chalk": "^5.6.2",
|
|
81
81
|
"cli-table3": "^0.6.5",
|
|
82
82
|
"commander": "^14.0.3",
|