agentvault 1.0.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/.dfx/local/network-id +4 -0
- package/.next/trace +2 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/PLAN_VAULT_INTEGRATION.md +318 -0
- package/README.md +253 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
- package/backups/test-backup.json +28 -0
- package/dist/cli/commands/approve.d.ts +4 -0
- package/dist/cli/commands/approve.js +232 -0
- package/dist/cli/commands/archive.d.ts +4 -0
- package/dist/cli/commands/archive.js +192 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.js +164 -0
- package/dist/cli/commands/cloud-backup.d.ts +4 -0
- package/dist/cli/commands/cloud-backup.js +221 -0
- package/dist/cli/commands/cycles.d.ts +8 -0
- package/dist/cli/commands/cycles.js +83 -0
- package/dist/cli/commands/decrypt.d.ts +16 -0
- package/dist/cli/commands/decrypt.js +101 -0
- package/dist/cli/commands/deploy.d.ts +32 -0
- package/dist/cli/commands/deploy.js +208 -0
- package/dist/cli/commands/exec.d.ts +26 -0
- package/dist/cli/commands/exec.js +109 -0
- package/dist/cli/commands/fetch.d.ts +23 -0
- package/dist/cli/commands/fetch.js +164 -0
- package/dist/cli/commands/health.d.ts +8 -0
- package/dist/cli/commands/health.js +72 -0
- package/dist/cli/commands/identity.d.ts +8 -0
- package/dist/cli/commands/identity.js +140 -0
- package/dist/cli/commands/inference.d.ts +4 -0
- package/dist/cli/commands/inference.js +225 -0
- package/dist/cli/commands/info.d.ts +8 -0
- package/dist/cli/commands/info.js +59 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.js +135 -0
- package/dist/cli/commands/instrument.d.ts +8 -0
- package/dist/cli/commands/instrument.js +35 -0
- package/dist/cli/commands/list.d.ts +36 -0
- package/dist/cli/commands/list.js +173 -0
- package/dist/cli/commands/logs.d.ts +8 -0
- package/dist/cli/commands/logs.js +96 -0
- package/dist/cli/commands/monitor.d.ts +8 -0
- package/dist/cli/commands/monitor.js +84 -0
- package/dist/cli/commands/network.d.ts +14 -0
- package/dist/cli/commands/network.js +258 -0
- package/dist/cli/commands/package.d.ts +36 -0
- package/dist/cli/commands/package.js +188 -0
- package/dist/cli/commands/profile.d.ts +8 -0
- package/dist/cli/commands/profile.js +76 -0
- package/dist/cli/commands/promote.d.ts +8 -0
- package/dist/cli/commands/promote.js +89 -0
- package/dist/cli/commands/rebuild.d.ts +21 -0
- package/dist/cli/commands/rebuild.js +140 -0
- package/dist/cli/commands/rollback.d.ts +8 -0
- package/dist/cli/commands/rollback.js +120 -0
- package/dist/cli/commands/show.d.ts +36 -0
- package/dist/cli/commands/show.js +200 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.js +34 -0
- package/dist/cli/commands/status.d.ts +14 -0
- package/dist/cli/commands/status.js +83 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +109 -0
- package/dist/cli/commands/tokens.d.ts +8 -0
- package/dist/cli/commands/tokens.js +62 -0
- package/dist/cli/commands/trace.d.ts +8 -0
- package/dist/cli/commands/trace.js +68 -0
- package/dist/cli/commands/wallet-export.d.ts +13 -0
- package/dist/cli/commands/wallet-export.js +140 -0
- package/dist/cli/commands/wallet-history.d.ts +10 -0
- package/dist/cli/commands/wallet-history.js +127 -0
- package/dist/cli/commands/wallet-import.d.ts +10 -0
- package/dist/cli/commands/wallet-import.js +209 -0
- package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
- package/dist/cli/commands/wallet-multi-send.js +195 -0
- package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
- package/dist/cli/commands/wallet-process-queue.js +209 -0
- package/dist/cli/commands/wallet-sign.d.ts +13 -0
- package/dist/cli/commands/wallet-sign.js +207 -0
- package/dist/cli/commands/wallet.d.ts +12 -0
- package/dist/cli/commands/wallet.js +794 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +96 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.js +14 -0
- package/fixup_1_0_OSS_release.md +136 -0
- package/fixup_REALEASE_PRD.md +136 -0
- package/package.json +79 -0
- package/pnpm-workspace.yaml +5 -0
- package/scripts/dev-dashboard.mjs +84 -0
- package/site/README.md +63 -0
- package/site/docusaurus.config.ts +148 -0
- package/site/package-lock.json +18383 -0
- package/site/package.json +47 -0
- package/site/sidebars.ts +86 -0
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +28 -0
- package/site/static/img/og-image.svg +35 -0
- package/src/archival/archive-manager.ts +372 -0
- package/src/archival/arweave-client.ts +289 -0
- package/src/archival/index.ts +8 -0
- package/src/backup/backup.ts +315 -0
- package/src/backup/index.ts +7 -0
- package/src/cloud-storage/cloud-sync.ts +461 -0
- package/src/cloud-storage/index.ts +11 -0
- package/src/cloud-storage/provider-detector.ts +198 -0
- package/src/cloud-storage/types.ts +104 -0
- package/src/debugging/index.ts +6 -0
- package/src/debugging/logs.ts +193 -0
- package/src/debugging/types.ts +100 -0
- package/src/deployment/deployer.ts +274 -0
- package/src/deployment/icpClient.ts +620 -0
- package/src/deployment/index.ts +46 -0
- package/src/deployment/promotion.ts +161 -0
- package/src/deployment/types.ts +111 -0
- package/src/icp/batch.ts +374 -0
- package/src/icp/cycles.ts +50 -0
- package/src/icp/environment.ts +215 -0
- package/src/icp/icpcli.ts +438 -0
- package/src/icp/icwasm.ts +222 -0
- package/src/icp/identity.ts +77 -0
- package/src/icp/index.ts +94 -0
- package/src/icp/optimization.ts +242 -0
- package/src/icp/tokens.ts +36 -0
- package/src/icp/tool-detector.ts +110 -0
- package/src/icp/types.ts +574 -0
- package/src/index.ts +25 -0
- package/src/inference/bittensor-client.ts +304 -0
- package/src/inference/index.ts +8 -0
- package/src/inference/inference-manager.ts +327 -0
- package/src/metrics/index.ts +7 -0
- package/src/metrics/metrics.ts +186 -0
- package/src/monitoring/alerting.ts +190 -0
- package/src/monitoring/health.ts +197 -0
- package/src/monitoring/index.ts +38 -0
- package/src/monitoring/info.ts +114 -0
- package/src/monitoring/types.ts +99 -0
- package/src/network/index.ts +5 -0
- package/src/network/network-config.ts +129 -0
- package/src/packaging/compiler.ts +647 -0
- package/src/packaging/config-persistence.ts +135 -0
- package/src/packaging/config-schemas.ts +156 -0
- package/src/packaging/detector.ts +220 -0
- package/src/packaging/index.ts +90 -0
- package/src/packaging/packager.ts +118 -0
- package/src/packaging/parsers/clawdbot.ts +278 -0
- package/src/packaging/parsers/cline.ts +223 -0
- package/src/packaging/parsers/generic.ts +266 -0
- package/src/packaging/parsers/goose.ts +214 -0
- package/src/packaging/parsers/index.ts +11 -0
- package/src/packaging/serializer.ts +260 -0
- package/src/packaging/types.ts +144 -0
- package/src/packaging/wasmedge-compiler.ts +406 -0
- package/src/security/index.ts +17 -0
- package/src/security/multisig.ts +415 -0
- package/src/security/types.ts +416 -0
- package/src/security/vetkeys.ts +655 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/local-runner.ts +264 -0
- package/src/testing/types.ts +104 -0
- package/src/wallet/cbor-serializer.ts +323 -0
- package/src/wallet/chain-dispatcher.ts +313 -0
- package/src/wallet/cross-chain-aggregator.ts +346 -0
- package/src/wallet/index.ts +76 -0
- package/src/wallet/key-derivation.ts +425 -0
- package/src/wallet/providers/base-provider.ts +154 -0
- package/src/wallet/providers/cketh-provider.ts +434 -0
- package/src/wallet/providers/polkadot-provider.ts +503 -0
- package/src/wallet/providers/solana-provider.ts +490 -0
- package/src/wallet/transaction-queue.ts +284 -0
- package/src/wallet/types.ts +178 -0
- package/src/wallet/vetkeys-adapter.ts +431 -0
- package/src/wallet/wallet-manager.ts +597 -0
- package/src/wallet/wallet-storage.ts +380 -0
- package/vercel.json +8 -0
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polkadot Wallet Provider (Full Implementation)
|
|
3
|
+
*
|
|
4
|
+
* Complete provider for Polkadot wallet operations.
|
|
5
|
+
* Integrates with @polkadot/util-crypto for key derivation.
|
|
6
|
+
* Uses @polkadot/api for real RPC network interactions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type {
|
|
10
|
+
Balance,
|
|
11
|
+
Transaction,
|
|
12
|
+
TransactionRequest,
|
|
13
|
+
SignedTransaction,
|
|
14
|
+
ProviderConfig,
|
|
15
|
+
} from '../types.js';
|
|
16
|
+
import { BaseWalletProvider } from './base-provider.js';
|
|
17
|
+
import {
|
|
18
|
+
sr25519PairFromSeed,
|
|
19
|
+
sr25519Sign,
|
|
20
|
+
checkAddress,
|
|
21
|
+
cryptoWaitReady,
|
|
22
|
+
} from '@polkadot/util-crypto';
|
|
23
|
+
import {
|
|
24
|
+
u8aToHex,
|
|
25
|
+
hexToU8a,
|
|
26
|
+
} from '@polkadot/util';
|
|
27
|
+
import { ApiPromise, WsProvider } from '@polkadot/api';
|
|
28
|
+
import type { KeyringPair } from '@polkadot/keyring/types';
|
|
29
|
+
import { Keyring } from '@polkadot/keyring';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Polkadot provider configuration
|
|
33
|
+
*/
|
|
34
|
+
interface PolkadotConfig extends ProviderConfig {
|
|
35
|
+
/** Polkadot JSON-RPC endpoint (WS or HTTP) */
|
|
36
|
+
rpcUrl: string;
|
|
37
|
+
/** Chain type (mainnet, testnet, dev) */
|
|
38
|
+
network?: 'mainnet' | 'testnet' | 'dev';
|
|
39
|
+
/** Chain type (polkadot, kusama, westend, astar) */
|
|
40
|
+
chainType?: 'polkadot' | 'kusama' | 'westend' | 'astar';
|
|
41
|
+
/** SS58 prefix for address encoding */
|
|
42
|
+
ss58Format?: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Polkadot wallet provider
|
|
47
|
+
*/
|
|
48
|
+
export class PolkadotProvider extends BaseWalletProvider {
|
|
49
|
+
private keyringPair: KeyringPair | null = null;
|
|
50
|
+
private api: ApiPromise | null = null;
|
|
51
|
+
private ss58Format: number;
|
|
52
|
+
private chainType: string;
|
|
53
|
+
|
|
54
|
+
constructor(config: PolkadotConfig) {
|
|
55
|
+
super(config);
|
|
56
|
+
this.ss58Format = config.ss58Format || 0;
|
|
57
|
+
this.chainType = config.chainType || 'polkadot';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private getApi() {
|
|
61
|
+
if (!this.api) {
|
|
62
|
+
throw new Error('API not connected');
|
|
63
|
+
}
|
|
64
|
+
return this.api;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private getSystemQuery() {
|
|
68
|
+
return this.getApi().query.system as any;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private getBalancesTx() {
|
|
72
|
+
return this.getApi().tx.balances as any;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private getRpcChain() {
|
|
76
|
+
return this.getApi().rpc.chain as any;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Connect to Polkadot network via RPC
|
|
81
|
+
*/
|
|
82
|
+
async connect(): Promise<void> {
|
|
83
|
+
try {
|
|
84
|
+
await cryptoWaitReady();
|
|
85
|
+
|
|
86
|
+
const rpcUrl = this.config.rpcUrl || this.getDefaultRpcUrl();
|
|
87
|
+
const provider = new WsProvider(rpcUrl);
|
|
88
|
+
|
|
89
|
+
this.api = await ApiPromise.create({ provider });
|
|
90
|
+
|
|
91
|
+
await this.api.isReady;
|
|
92
|
+
|
|
93
|
+
this.connected = true;
|
|
94
|
+
console.log(`Connected to ${this.chainType} network via ${rpcUrl}`);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
97
|
+
throw new Error(`Failed to connect to Polkadot network: ${message}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Disconnect from Polkadot network
|
|
103
|
+
*/
|
|
104
|
+
async disconnect(): Promise<void> {
|
|
105
|
+
if (this.api) {
|
|
106
|
+
await this.api.disconnect();
|
|
107
|
+
this.api = null;
|
|
108
|
+
}
|
|
109
|
+
this.keyringPair = null;
|
|
110
|
+
this.connected = false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get wallet balance
|
|
115
|
+
*/
|
|
116
|
+
async getBalance(address: string): Promise<Balance> {
|
|
117
|
+
if (!this.connected || !this.api) {
|
|
118
|
+
throw new Error('Provider not connected');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const accountInfo = await this.getSystemQuery().account(address);
|
|
123
|
+
const data = accountInfo.toJSON() as any;
|
|
124
|
+
const freeBalance = ((data?.data?.free as string) ?? '0');
|
|
125
|
+
const reserved = ((data?.data?.reserved as string) ?? '0');
|
|
126
|
+
const totalBalance = (BigInt(freeBalance) + BigInt(reserved)).toString();
|
|
127
|
+
|
|
128
|
+
const balanceInDot = parseFloat(totalBalance) / 10_000_000_000;
|
|
129
|
+
|
|
130
|
+
const blockNumber = await this.getSystemQuery().number();
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
amount: balanceInDot.toString(),
|
|
134
|
+
denomination: 'DOT',
|
|
135
|
+
chain: this.chainType as any,
|
|
136
|
+
address,
|
|
137
|
+
blockNumber: Number(blockNumber),
|
|
138
|
+
};
|
|
139
|
+
} catch (error) {
|
|
140
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
141
|
+
throw new Error(`Failed to get balance: ${message}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Send transaction
|
|
147
|
+
*/
|
|
148
|
+
async sendTransaction(
|
|
149
|
+
from: string,
|
|
150
|
+
request: TransactionRequest
|
|
151
|
+
): Promise<Transaction> {
|
|
152
|
+
if (!this.connected || !this.api || !this.keyringPair) {
|
|
153
|
+
throw new Error('Provider not connected or no wallet loaded');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const transferAmount = this.parseDotAmount(request.amount);
|
|
158
|
+
|
|
159
|
+
const tx = this.getBalancesTx().transfer(request.to, transferAmount);
|
|
160
|
+
|
|
161
|
+
const hash = await tx.signAndSend(this.keyringPair);
|
|
162
|
+
|
|
163
|
+
const fee = await this.estimateFee(request);
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
hash: hash.toString(),
|
|
167
|
+
from,
|
|
168
|
+
to: request.to,
|
|
169
|
+
amount: request.amount,
|
|
170
|
+
chain: this.chainType as any,
|
|
171
|
+
timestamp: Date.now(),
|
|
172
|
+
status: 'pending',
|
|
173
|
+
fee,
|
|
174
|
+
data: { memo: request.memo },
|
|
175
|
+
};
|
|
176
|
+
} catch (error) {
|
|
177
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
178
|
+
throw new Error(`Failed to send transaction: ${message}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Sign transaction
|
|
184
|
+
*/
|
|
185
|
+
async signTransaction(
|
|
186
|
+
tx: any,
|
|
187
|
+
privateKey: string
|
|
188
|
+
): Promise<SignedTransaction> {
|
|
189
|
+
if (!this.api) {
|
|
190
|
+
throw new Error('Provider not connected');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
const keypair = this.createKeyringPair(privateKey);
|
|
195
|
+
const transferAmount = this.parseDotAmount(tx.amount);
|
|
196
|
+
|
|
197
|
+
const unsignedTx = this.getBalancesTx().transfer(tx.to, transferAmount);
|
|
198
|
+
const signedTx = await unsignedTx.signAsync(keypair);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
txHash: signedTx.hash.toString(),
|
|
202
|
+
signedTx: signedTx.toHex(),
|
|
203
|
+
signature: u8aToHex(signedTx.signature),
|
|
204
|
+
request: tx,
|
|
205
|
+
};
|
|
206
|
+
} catch (error) {
|
|
207
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
208
|
+
throw new Error(`Failed to sign transaction: ${message}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Get transaction history
|
|
214
|
+
*/
|
|
215
|
+
async getTransactionHistory(address: string): Promise<Transaction[]> {
|
|
216
|
+
if (!this.connected || !this.api) {
|
|
217
|
+
throw new Error('Provider not connected');
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
try {
|
|
221
|
+
const transactions: Transaction[] = [];
|
|
222
|
+
|
|
223
|
+
const blockNumber = await this.getSystemQuery().number();
|
|
224
|
+
const latestBlocks = Math.min(Number(blockNumber), 100);
|
|
225
|
+
|
|
226
|
+
for (let i = 0; i < latestBlocks; i++) {
|
|
227
|
+
const blockHash = await this.getRpcChain().getBlockHash(Number(blockNumber) - i);
|
|
228
|
+
|
|
229
|
+
const events = await this.getSystemQuery().events.at(blockHash);
|
|
230
|
+
const eventRecords = events.toHuman() as any[];
|
|
231
|
+
|
|
232
|
+
for (const event of eventRecords) {
|
|
233
|
+
if (event.event?.section === 'balances' && event.event?.method === 'Transfer') {
|
|
234
|
+
const eventData = event.event.data;
|
|
235
|
+
const [from, to, amount] = eventData;
|
|
236
|
+
|
|
237
|
+
if (from.toString() === address || to.toString() === address) {
|
|
238
|
+
transactions.push({
|
|
239
|
+
hash: blockHash.toString(),
|
|
240
|
+
from: from.toString(),
|
|
241
|
+
to: to.toString(),
|
|
242
|
+
amount: this.formatPlancks(amount.toString()),
|
|
243
|
+
chain: this.chainType as any,
|
|
244
|
+
timestamp: Date.now() - (i * 6000),
|
|
245
|
+
status: 'confirmed',
|
|
246
|
+
fee: '0',
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return transactions.slice(0, 20);
|
|
254
|
+
} catch (error) {
|
|
255
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
256
|
+
console.warn(`Failed to get transaction history: ${message}`);
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Validate Polkadot address (SS58 format)
|
|
263
|
+
*/
|
|
264
|
+
validateAddress(address: string): boolean {
|
|
265
|
+
try {
|
|
266
|
+
const [isValid] = checkAddress(address, this.ss58Format);
|
|
267
|
+
return isValid;
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Estimate transaction fee
|
|
275
|
+
*/
|
|
276
|
+
async estimateFee(request: TransactionRequest): Promise<string> {
|
|
277
|
+
if (!this.connected || !this.api || !this.keyringPair) {
|
|
278
|
+
return '0.01';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
try {
|
|
282
|
+
const transferAmount = this.parseDotAmount(request.amount);
|
|
283
|
+
|
|
284
|
+
const tx = this.getBalancesTx().transfer(request.to, transferAmount);
|
|
285
|
+
|
|
286
|
+
const info = await tx.paymentInfo(this.keyringPair);
|
|
287
|
+
|
|
288
|
+
const partialFee = info.partialFee.toString();
|
|
289
|
+
const feeInDot = parseFloat(partialFee) / 10_000_000_000;
|
|
290
|
+
|
|
291
|
+
return feeInDot.toFixed(6);
|
|
292
|
+
} catch (_error) {
|
|
293
|
+
return '0.01';
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Get current block number
|
|
299
|
+
*/
|
|
300
|
+
async getBlockNumber(): Promise<number> {
|
|
301
|
+
if (!this.connected || !this.api) {
|
|
302
|
+
throw new Error('Provider not connected');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
const blockNumber = await this.getSystemQuery().number();
|
|
307
|
+
return Number(blockNumber);
|
|
308
|
+
} catch (error) {
|
|
309
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
310
|
+
throw new Error(`Failed to get block number: ${message}`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Get transaction by hash
|
|
316
|
+
*/
|
|
317
|
+
async getTransaction(txHash: string): Promise<Transaction | null> {
|
|
318
|
+
if (!this.connected || !this.api) {
|
|
319
|
+
throw new Error('Provider not connected');
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
try {
|
|
323
|
+
const blockHash = await this.getRpcChain().getBlockHash();
|
|
324
|
+
const events = await this.getSystemQuery().events.at(blockHash || undefined);
|
|
325
|
+
const eventRecords = events.toHuman() as any[];
|
|
326
|
+
|
|
327
|
+
let from = '';
|
|
328
|
+
let to = '';
|
|
329
|
+
let amount = '0';
|
|
330
|
+
let found = false;
|
|
331
|
+
|
|
332
|
+
for (const event of eventRecords) {
|
|
333
|
+
if (event.event?.section === 'balances' && event.event?.method === 'Transfer' && event.event?.data) {
|
|
334
|
+
const eventData = event.event?.data as [string, string, string];
|
|
335
|
+
[from, to, amount] = eventData;
|
|
336
|
+
found = true;
|
|
337
|
+
}
|
|
338
|
+
if (event.event?.section === 'system' && event.event?.method === 'ExtrinsicSuccess') {
|
|
339
|
+
break;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (found && (from || to)) {
|
|
344
|
+
return {
|
|
345
|
+
hash: txHash,
|
|
346
|
+
from: from.toString(),
|
|
347
|
+
to: to.toString(),
|
|
348
|
+
amount: this.formatPlancks(amount.toString()),
|
|
349
|
+
chain: this.chainType as any,
|
|
350
|
+
timestamp: Date.now(),
|
|
351
|
+
status: 'confirmed',
|
|
352
|
+
fee: '0',
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return null;
|
|
357
|
+
} catch (error) {
|
|
358
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
359
|
+
throw new Error(`Failed to get transaction: ${message}`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Initialize keypair from wallet data
|
|
365
|
+
*/
|
|
366
|
+
async initKeypair(mnemonic: string, derivationPath?: string): Promise<void> {
|
|
367
|
+
try {
|
|
368
|
+
await cryptoWaitReady();
|
|
369
|
+
|
|
370
|
+
const keyring = new Keyring({ type: 'sr25519', ss58Format: this.ss58Format });
|
|
371
|
+
|
|
372
|
+
const path = derivationPath || '//hard//stash';
|
|
373
|
+
|
|
374
|
+
this.keyringPair = keyring.addFromMnemonic(mnemonic, undefined, 'sr25519');
|
|
375
|
+
|
|
376
|
+
if (derivationPath && derivationPath !== '//hard//stash') {
|
|
377
|
+
const derived = keyring.addFromUri(path, undefined, 'sr25519');
|
|
378
|
+
this.keyringPair = derived;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
console.log('Polkadot keypair initialized for derivation:', path);
|
|
382
|
+
console.log('Address:', this.getAddress());
|
|
383
|
+
} catch (error) {
|
|
384
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
385
|
+
throw new Error(`Failed to initialize Polkadot keypair: ${message}`);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Initialize from private key
|
|
391
|
+
*/
|
|
392
|
+
async initFromPrivateKey(privateKey: string): Promise<void> {
|
|
393
|
+
try {
|
|
394
|
+
this.keyringPair = this.createKeyringPair(privateKey);
|
|
395
|
+
|
|
396
|
+
console.log('Polkadot keypair initialized from private key');
|
|
397
|
+
console.log('Address:', this.getAddress());
|
|
398
|
+
} catch (error) {
|
|
399
|
+
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
400
|
+
throw new Error(`Failed to initialize Polkadot keypair from private key: ${message}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Create KeyringPair from private key
|
|
406
|
+
*/
|
|
407
|
+
private createKeyringPair(privateKeyHex: string): KeyringPair {
|
|
408
|
+
const keyring = new Keyring({ type: 'sr25519', ss58Format: this.ss58Format });
|
|
409
|
+
const privateKeyBytes = hexToU8a(privateKeyHex);
|
|
410
|
+
const pair = keyring.addFromSeed(privateKeyBytes);
|
|
411
|
+
return pair;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Get address from keypair
|
|
416
|
+
*/
|
|
417
|
+
getAddress(): string | null {
|
|
418
|
+
if (!this.keyringPair) {
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return this.keyringPair.address;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Get public key
|
|
427
|
+
*/
|
|
428
|
+
getPublicKey(): string | null {
|
|
429
|
+
if (!this.keyringPair) {
|
|
430
|
+
return null;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return u8aToHex(this.keyringPair.publicKey);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Parse DOT amount (convert from string to Plancks)
|
|
438
|
+
*/
|
|
439
|
+
private parseDotAmount(amountStr: string): bigint {
|
|
440
|
+
try {
|
|
441
|
+
const cleanAmount = amountStr.replace(/,/g, '').trim();
|
|
442
|
+
const amount = parseFloat(cleanAmount);
|
|
443
|
+
const plancks = Math.floor(amount * 10_000_000_000);
|
|
444
|
+
return BigInt(plancks);
|
|
445
|
+
} catch (_error) {
|
|
446
|
+
return BigInt(0);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Format Plancks to DOT
|
|
452
|
+
*/
|
|
453
|
+
private formatPlancks(plancks: string): string {
|
|
454
|
+
try {
|
|
455
|
+
const amount = parseFloat(plancks) / 10_000_000_000;
|
|
456
|
+
return amount.toFixed(6);
|
|
457
|
+
} catch (_error) {
|
|
458
|
+
return '0';
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Create SR25519 signature for transaction
|
|
464
|
+
*/
|
|
465
|
+
async createSignature(
|
|
466
|
+
payload: Uint8Array,
|
|
467
|
+
privateKeyHex: string
|
|
468
|
+
): Promise<Uint8Array> {
|
|
469
|
+
try {
|
|
470
|
+
const privateKeyBytes = hexToU8a(privateKeyHex);
|
|
471
|
+
const keypair = sr25519PairFromSeed(privateKeyBytes);
|
|
472
|
+
|
|
473
|
+
const signature = sr25519Sign(payload, { publicKey: keypair.publicKey, secretKey: keypair.secretKey });
|
|
474
|
+
|
|
475
|
+
return signature;
|
|
476
|
+
} catch (error) {
|
|
477
|
+
const msg = error instanceof Error ? error.message : 'Unknown error';
|
|
478
|
+
throw new Error(`Failed to create Polkadot signature: ${msg}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Get default RPC URL for chain type
|
|
484
|
+
* Checks environment variables first, then falls back to public RPC endpoints
|
|
485
|
+
*/
|
|
486
|
+
private getDefaultRpcUrl(): string {
|
|
487
|
+
const envUrls: Record<string, string | undefined> = {
|
|
488
|
+
polkadot: process.env.POLKADOT_RPC_URL,
|
|
489
|
+
kusama: process.env.KUSAMA_RPC_URL,
|
|
490
|
+
westend: process.env.WESTEND_RPC_URL,
|
|
491
|
+
astar: process.env.ASTAR_RPC_URL,
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
const publicUrls: Record<string, string> = {
|
|
495
|
+
polkadot: 'wss://rpc.polkadot.io',
|
|
496
|
+
kusama: 'wss://kusama-rpc.polkadot.io',
|
|
497
|
+
westend: 'wss://westend-rpc.polkadot.io',
|
|
498
|
+
astar: 'wss://rpc.astar.network',
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
return envUrls[this.chainType] || publicUrls[this.chainType] || publicUrls.polkadot!;
|
|
502
|
+
}
|
|
503
|
+
}
|