@kairoguard/sdk 0.0.7 → 0.0.8
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/dist/client.js +36 -45
- package/dist/ika-protocol.d.ts +8 -0
- package/dist/ika-protocol.js +12 -0
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { BackendClient, } from "./backend.js";
|
|
12
12
|
import { KeyStore } from "./keystore.js";
|
|
13
|
-
import { Curve, fetchProtocolParams, deriveEncryptionKeys, generateSeed, generateSessionIdentifier, runDKG, computeUserOutputSignature, fetchDWallet, } from "./ika-protocol.js";
|
|
13
|
+
import { Curve, fetchProtocolParams, deriveEncryptionKeys, generateSeed, generateSessionIdentifier, runDKG, computeUserOutputSignature, fetchDWallet, waitForDWalletState, } from "./ika-protocol.js";
|
|
14
14
|
import { Hash, SignatureAlgorithm, createUserSignMessageWithPublicOutput } from "@ika.xyz/sdk";
|
|
15
15
|
import { computeEvmIntentFromUnsignedTxBytes } from "./evmIntent.js";
|
|
16
16
|
import { keccak256, recoverTransactionAddress, serializeTransaction, } from "viem";
|
|
@@ -64,6 +64,8 @@ const PRESIGN_POLL_INTERVAL_MS = 2_000;
|
|
|
64
64
|
const PRESIGN_POLL_TIMEOUT_MS = 120_000;
|
|
65
65
|
const SIGN_POLL_INTERVAL_MS = 2_000;
|
|
66
66
|
const SIGN_POLL_TIMEOUT_MS = 180_000;
|
|
67
|
+
const ACTIVATION_POLL_INTERVAL_MS = 3_000;
|
|
68
|
+
const ACTIVATION_POLL_TIMEOUT_MS = 90_000;
|
|
67
69
|
function curveToNumber(curve) {
|
|
68
70
|
return curve === "ed25519" ? 2 : 0;
|
|
69
71
|
}
|
|
@@ -149,21 +151,7 @@ export class KairoClient {
|
|
|
149
151
|
const walletId = dkgResult.dWalletObjectId;
|
|
150
152
|
const address = (curve === "ed25519" ? dkgResult.solanaAddress : dkgResult.ethereumAddress) ?? "";
|
|
151
153
|
const encryptedShareId = dkgResult.encryptedUserSecretKeyShareId ?? "";
|
|
152
|
-
// 8.
|
|
153
|
-
if (encryptedShareId) {
|
|
154
|
-
await this.activateWallet(walletId, encryptedShareId, encryptionKeys, dkgOutputs.userPublicOutput);
|
|
155
|
-
}
|
|
156
|
-
// 9. Provision into vault (binding + registration) if policy is provided
|
|
157
|
-
let bindingObjectId;
|
|
158
|
-
if (opts?.policyObjectId) {
|
|
159
|
-
const provisionResult = await this.backend.provision({
|
|
160
|
-
dwalletObjectId: walletId,
|
|
161
|
-
policyObjectId: opts.policyObjectId,
|
|
162
|
-
stableId: opts.stableId ?? `agent-wallet-${walletId.slice(0, 8)}`,
|
|
163
|
-
});
|
|
164
|
-
bindingObjectId = provisionResult.bindingObjectId ?? undefined;
|
|
165
|
-
}
|
|
166
|
-
// 10. Save secret share locally
|
|
154
|
+
// 8. Save secret share locally BEFORE activation so it is never lost
|
|
167
155
|
const record = {
|
|
168
156
|
walletId,
|
|
169
157
|
dWalletCapId: dkgResult.dWalletCapObjectId,
|
|
@@ -173,11 +161,26 @@ export class KairoClient {
|
|
|
173
161
|
userSecretKeyShare: dkgOutputs.userSecretKeyShare,
|
|
174
162
|
userPublicOutput: dkgOutputs.userPublicOutput,
|
|
175
163
|
encryptedUserSecretKeyShareId: encryptedShareId,
|
|
176
|
-
bindingObjectId,
|
|
164
|
+
bindingObjectId: undefined,
|
|
177
165
|
policyObjectId: opts?.policyObjectId,
|
|
178
166
|
createdAt: Date.now(),
|
|
179
167
|
};
|
|
180
168
|
this.store.save(record);
|
|
169
|
+
// 9. Activate the dWallet (sign to accept encrypted key share)
|
|
170
|
+
if (encryptedShareId) {
|
|
171
|
+
await this.activateWallet(walletId, encryptedShareId, encryptionKeys, dkgOutputs.userPublicOutput);
|
|
172
|
+
}
|
|
173
|
+
// 10. Provision into vault (binding + registration) if policy is provided
|
|
174
|
+
let bindingObjectId;
|
|
175
|
+
if (opts?.policyObjectId) {
|
|
176
|
+
const provisionResult = await this.backend.provision({
|
|
177
|
+
dwalletObjectId: walletId,
|
|
178
|
+
policyObjectId: opts.policyObjectId,
|
|
179
|
+
stableId: opts.stableId ?? `agent-wallet-${walletId.slice(0, 8)}`,
|
|
180
|
+
});
|
|
181
|
+
bindingObjectId = provisionResult.bindingObjectId ?? undefined;
|
|
182
|
+
this.store.save({ ...record, bindingObjectId });
|
|
183
|
+
}
|
|
181
184
|
return {
|
|
182
185
|
walletId,
|
|
183
186
|
address,
|
|
@@ -534,38 +537,26 @@ export class KairoClient {
|
|
|
534
537
|
return BigInt(balanceHex);
|
|
535
538
|
}
|
|
536
539
|
async activateWallet(walletId, encryptedShareId, encryptionKeys, userPublicOutput) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
if (!isAwaitingSignature) {
|
|
551
|
-
// Unknown state - wait and retry once
|
|
552
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
553
|
-
const dWallet2 = await withRetry(() => fetchDWallet(rpcUrlForActivation, this.network, walletId), { label: "fetchDWallet(activate-recheck)" });
|
|
554
|
-
const state2 = dWallet2?.state;
|
|
555
|
-
const isActive2 = Boolean(state2?.Active) || state2?.$kind === "Active";
|
|
556
|
-
if (isActive2)
|
|
540
|
+
const rpcUrl = await this.resolveSuiRpcUrl();
|
|
541
|
+
// After DKG the on-chain dWallet goes through AwaitingNetworkDKGVerification
|
|
542
|
+
// (30-60s+ on testnet). Use the Ika SDK's native polling to wait for the
|
|
543
|
+
// correct state before attempting activation.
|
|
544
|
+
let dWallet;
|
|
545
|
+
try {
|
|
546
|
+
dWallet = await waitForDWalletState(rpcUrl, this.network, walletId, "AwaitingKeyHolderSignature", { timeout: ACTIVATION_POLL_TIMEOUT_MS, interval: ACTIVATION_POLL_INTERVAL_MS });
|
|
547
|
+
}
|
|
548
|
+
catch {
|
|
549
|
+
// May already be Active (idempotent retry after earlier partial success)
|
|
550
|
+
const current = await withRetry(() => fetchDWallet(rpcUrl, this.network, walletId), { label: "fetchDWallet(activate-fallback)" });
|
|
551
|
+
const kind = String(current?.state?.$kind ?? "");
|
|
552
|
+
if (kind === "Active")
|
|
557
553
|
return;
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
if (!isAwaiting2) {
|
|
561
|
-
const stateKind = state2?.$kind ?? Object.keys(state2 ?? {})[0] ?? "Unknown";
|
|
562
|
-
throw new Error(`dWallet is not ready for activation (state=${stateKind}). ` +
|
|
563
|
-
`This can happen if the DKG is still processing. Wait a few seconds and retry.`);
|
|
564
|
-
}
|
|
554
|
+
throw new Error(`dWallet activation timed out after ${ACTIVATION_POLL_TIMEOUT_MS / 1000}s ` +
|
|
555
|
+
`(state=${kind || "Unknown"}). The wallet record is saved locally — retry later.`);
|
|
565
556
|
}
|
|
566
557
|
const signature = await computeUserOutputSignature({
|
|
567
558
|
encryptionKeys,
|
|
568
|
-
dWallet,
|
|
559
|
+
dWallet: dWallet,
|
|
569
560
|
userPublicOutput: new Uint8Array(userPublicOutput),
|
|
570
561
|
});
|
|
571
562
|
await this.backend.activateDWallet({
|
package/dist/ika-protocol.d.ts
CHANGED
|
@@ -54,6 +54,14 @@ export declare function computeUserOutputSignature(params: {
|
|
|
54
54
|
* Fetch the dWallet object from Ika network for activation.
|
|
55
55
|
*/
|
|
56
56
|
export declare function fetchDWallet(suiRpcUrl: string, network: "testnet" | "mainnet", dwalletId: string): Promise<any>;
|
|
57
|
+
/**
|
|
58
|
+
* Poll until the dWallet reaches `targetState` using the Ika SDK's native
|
|
59
|
+
* getDWalletInParticularState, which handles reindexing/lag gracefully.
|
|
60
|
+
*/
|
|
61
|
+
export declare function waitForDWalletState(suiRpcUrl: string, network: "testnet" | "mainnet", dwalletId: string, targetState: "AwaitingKeyHolderSignature" | "Active", opts?: {
|
|
62
|
+
timeout?: number;
|
|
63
|
+
interval?: number;
|
|
64
|
+
}): Promise<any>;
|
|
57
65
|
export interface ComputeUserSignMessageParams {
|
|
58
66
|
protocolPublicParameters: Uint8Array;
|
|
59
67
|
userPublicOutput: Uint8Array;
|
package/dist/ika-protocol.js
CHANGED
|
@@ -98,6 +98,18 @@ export async function fetchDWallet(suiRpcUrl, network, dwalletId) {
|
|
|
98
98
|
await ready;
|
|
99
99
|
return ikaClient.getDWallet(dwalletId);
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Poll until the dWallet reaches `targetState` using the Ika SDK's native
|
|
103
|
+
* getDWalletInParticularState, which handles reindexing/lag gracefully.
|
|
104
|
+
*/
|
|
105
|
+
export async function waitForDWalletState(suiRpcUrl, network, dwalletId, targetState, opts) {
|
|
106
|
+
const { ikaClient, ready } = getOrCreateIkaClient(network, suiRpcUrl);
|
|
107
|
+
await ready;
|
|
108
|
+
return ikaClient.getDWalletInParticularState(dwalletId, targetState, {
|
|
109
|
+
timeout: opts?.timeout ?? 90_000,
|
|
110
|
+
interval: opts?.interval ?? 3_000,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
101
113
|
/**
|
|
102
114
|
* Build the user-side sign message used by IKA MPC signing.
|
|
103
115
|
*/
|