@owney/sdk 0.7.7-beta.6 → 0.7.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/dist/index.cjs +132 -16
- package/dist/index.d.cts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +117 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2025,7 +2025,7 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
2025
2025
|
}
|
|
2026
2026
|
|
|
2027
2027
|
// src/client.ts
|
|
2028
|
-
var
|
|
2028
|
+
var import_viem6 = require("viem");
|
|
2029
2029
|
var import_chains2 = require("viem/chains");
|
|
2030
2030
|
|
|
2031
2031
|
// src/lib/transfer-auth.ts
|
|
@@ -2455,6 +2455,97 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2455
2455
|
};
|
|
2456
2456
|
}
|
|
2457
2457
|
|
|
2458
|
+
// src/lib/sponsored-calls-deposit.ts
|
|
2459
|
+
var import_viem5 = require("viem");
|
|
2460
|
+
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
2461
|
+
var DEFAULT_MAX_POLLS = 30;
|
|
2462
|
+
async function paymasterSupported(provider, owner, chainId) {
|
|
2463
|
+
const caps = await provider.request({
|
|
2464
|
+
method: "wallet_getCapabilities",
|
|
2465
|
+
params: [owner]
|
|
2466
|
+
});
|
|
2467
|
+
const forChain = caps?.[(0, import_viem5.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
2468
|
+
return Boolean(forChain?.paymasterService?.supported);
|
|
2469
|
+
}
|
|
2470
|
+
function makeSponsoredCallsCallback(deps) {
|
|
2471
|
+
const pollIntervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
2472
|
+
const maxPolls = deps.maxPolls ?? DEFAULT_MAX_POLLS;
|
|
2473
|
+
const absolutePaymasterUrl = () => {
|
|
2474
|
+
const configured = deps.paymasterServiceUrl;
|
|
2475
|
+
if (/^https?:\/\//i.test(configured)) return configured;
|
|
2476
|
+
const origin = globalThis.location?.origin;
|
|
2477
|
+
if (!origin) {
|
|
2478
|
+
throw new OwneyError(
|
|
2479
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2480
|
+
`paymasterServiceUrl "${configured}" is relative and no page origin is available to resolve it.`
|
|
2481
|
+
);
|
|
2482
|
+
}
|
|
2483
|
+
return new URL(configured, origin).toString();
|
|
2484
|
+
};
|
|
2485
|
+
return async (smartWallet, chainId, amount) => {
|
|
2486
|
+
const cid = chainId;
|
|
2487
|
+
const token = deps.tokenAddressByChain[cid];
|
|
2488
|
+
if (!token) {
|
|
2489
|
+
throw new OwneyError(
|
|
2490
|
+
"CHAIN_UNSUPPORTED",
|
|
2491
|
+
`No sponsored token configured for chain ${chainId}`
|
|
2492
|
+
);
|
|
2493
|
+
}
|
|
2494
|
+
if (!await paymasterSupported(deps.provider, deps.ownerAddress, chainId)) {
|
|
2495
|
+
throw new OwneyError(
|
|
2496
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2497
|
+
`Wallet does not advertise paymasterService on chain ${chainId}.`,
|
|
2498
|
+
{ chainId }
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
const data = (0, import_viem5.encodeFunctionData)({
|
|
2502
|
+
abi: import_viem5.erc20Abi,
|
|
2503
|
+
functionName: "transfer",
|
|
2504
|
+
args: [smartWallet, BigInt(amount)]
|
|
2505
|
+
});
|
|
2506
|
+
const sendResult = await deps.provider.request({
|
|
2507
|
+
method: "wallet_sendCalls",
|
|
2508
|
+
params: [
|
|
2509
|
+
{
|
|
2510
|
+
version: "2.0.0",
|
|
2511
|
+
from: deps.ownerAddress,
|
|
2512
|
+
chainId: (0, import_viem5.toHex)(chainId),
|
|
2513
|
+
atomicRequired: false,
|
|
2514
|
+
calls: [{ to: token, value: "0x0", data }],
|
|
2515
|
+
capabilities: {
|
|
2516
|
+
paymasterService: { url: absolutePaymasterUrl() }
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
]
|
|
2520
|
+
});
|
|
2521
|
+
deps.onApproved?.();
|
|
2522
|
+
const callsId = typeof sendResult === "string" ? sendResult : sendResult?.id;
|
|
2523
|
+
if (!callsId) {
|
|
2524
|
+
throw new OwneyError(
|
|
2525
|
+
"SPONSORED_CALLS_NO_ID",
|
|
2526
|
+
"Wallet accepted wallet_sendCalls but returned no calls id.",
|
|
2527
|
+
{ chainId }
|
|
2528
|
+
);
|
|
2529
|
+
}
|
|
2530
|
+
for (let attempt = 0; attempt < maxPolls; attempt += 1) {
|
|
2531
|
+
const status = await deps.provider.request({
|
|
2532
|
+
method: "wallet_getCallsStatus",
|
|
2533
|
+
params: [callsId]
|
|
2534
|
+
});
|
|
2535
|
+
const txHash = status?.receipts?.[0]?.transactionHash;
|
|
2536
|
+
if (txHash) return txHash;
|
|
2537
|
+
if (pollIntervalMs > 0) {
|
|
2538
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
throw new OwneyError(
|
|
2542
|
+
"SPONSORED_CALLS_NO_RECEIPT",
|
|
2543
|
+
`No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
|
|
2544
|
+
{ chainId, callsId }
|
|
2545
|
+
);
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2458
2549
|
// src/client.ts
|
|
2459
2550
|
function encodeMultiAgentCursor(map) {
|
|
2460
2551
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -2516,12 +2607,15 @@ var OwneySDK = class {
|
|
|
2516
2607
|
referralSource;
|
|
2517
2608
|
cachedSponsoredCallback = null;
|
|
2518
2609
|
cachedWethSponsoredCallback = null;
|
|
2610
|
+
paymasterServiceUrl;
|
|
2611
|
+
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2519
2612
|
initializingAgentsPromise = null;
|
|
2520
2613
|
constructor(config) {
|
|
2521
2614
|
this.apiKey = config.apiKey;
|
|
2522
2615
|
if (config.debug) setOwneyDebug(true);
|
|
2523
2616
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
2524
2617
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
2618
|
+
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
2525
2619
|
this.referralSource = config.referralSource;
|
|
2526
2620
|
}
|
|
2527
2621
|
/**
|
|
@@ -2544,6 +2638,7 @@ var OwneySDK = class {
|
|
|
2544
2638
|
this.state = { provider, walletAddress, chainId: null };
|
|
2545
2639
|
this.cachedSponsoredCallback = null;
|
|
2546
2640
|
this.cachedWethSponsoredCallback = null;
|
|
2641
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2547
2642
|
}
|
|
2548
2643
|
/**
|
|
2549
2644
|
* Disconnect from all agents and clear connection state.
|
|
@@ -2558,6 +2653,7 @@ var OwneySDK = class {
|
|
|
2558
2653
|
this.state = null;
|
|
2559
2654
|
this.cachedSponsoredCallback = null;
|
|
2560
2655
|
this.cachedWethSponsoredCallback = null;
|
|
2656
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2561
2657
|
}
|
|
2562
2658
|
isAgentDisabled(agentId) {
|
|
2563
2659
|
return this.disabledAgents.has(agentId);
|
|
@@ -2620,14 +2716,14 @@ var OwneySDK = class {
|
|
|
2620
2716
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
2621
2717
|
// PublicClient/WalletClient param types — structurally identical at
|
|
2622
2718
|
// runtime, but the two share a name TS treats as unrelated.
|
|
2623
|
-
getPublicClient: (cid) => (0,
|
|
2719
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
2624
2720
|
chain: VIEM_CHAIN2[cid],
|
|
2625
|
-
transport: (0,
|
|
2721
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2626
2722
|
}),
|
|
2627
|
-
getWalletClient: (cid) => (0,
|
|
2723
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
2628
2724
|
account: owner,
|
|
2629
2725
|
chain: VIEM_CHAIN2[cid],
|
|
2630
|
-
transport: (0,
|
|
2726
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2631
2727
|
})
|
|
2632
2728
|
});
|
|
2633
2729
|
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
@@ -2639,6 +2735,26 @@ var OwneySDK = class {
|
|
|
2639
2735
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2640
2736
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2641
2737
|
*/
|
|
2738
|
+
getDefaultSponsoredCallsCallback(asset, onApproved) {
|
|
2739
|
+
const cached = this.cachedSponsoredCallsCallbacks.get(asset);
|
|
2740
|
+
if (!onApproved && cached) return cached;
|
|
2741
|
+
const provider = this.requireConnectedProvider();
|
|
2742
|
+
const callback = makeSponsoredCallsCallback({
|
|
2743
|
+
provider,
|
|
2744
|
+
ownerAddress: this.state.walletAddress,
|
|
2745
|
+
paymasterServiceUrl: this.paymasterServiceUrl,
|
|
2746
|
+
onApproved,
|
|
2747
|
+
tokenAddressByChain: asset === "WETH" ? SPONSORED_WETH_BY_CHAIN : SPONSORED_USDC_BY_CHAIN
|
|
2748
|
+
});
|
|
2749
|
+
if (!onApproved) this.cachedSponsoredCallsCallbacks.set(asset, callback);
|
|
2750
|
+
return callback;
|
|
2751
|
+
}
|
|
2752
|
+
/**
|
|
2753
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
2754
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
2755
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2756
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2757
|
+
*/
|
|
2642
2758
|
getDefaultWethSponsoredCallback(onApproved) {
|
|
2643
2759
|
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
2644
2760
|
return this.cachedWethSponsoredCallback;
|
|
@@ -2653,14 +2769,14 @@ var OwneySDK = class {
|
|
|
2653
2769
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
2654
2770
|
// PublicClient/WalletClient param types — structurally identical at
|
|
2655
2771
|
// runtime, but the two share a name TS treats as unrelated.
|
|
2656
|
-
getPublicClient: (cid) => (0,
|
|
2772
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
2657
2773
|
chain: VIEM_CHAIN2[cid],
|
|
2658
|
-
transport: (0,
|
|
2774
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2659
2775
|
}),
|
|
2660
|
-
getWalletClient: (cid) => (0,
|
|
2776
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
2661
2777
|
account: owner,
|
|
2662
2778
|
chain: VIEM_CHAIN2[cid],
|
|
2663
|
-
transport: (0,
|
|
2779
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2664
2780
|
})
|
|
2665
2781
|
});
|
|
2666
2782
|
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
@@ -2861,7 +2977,7 @@ var OwneySDK = class {
|
|
|
2861
2977
|
}
|
|
2862
2978
|
const state = this.requireState();
|
|
2863
2979
|
const chainId = this.requireChainId();
|
|
2864
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2980
|
+
const effectiveCallback = depositCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2865
2981
|
if (agentId) {
|
|
2866
2982
|
if (this.isAgentDisabled(agentId)) {
|
|
2867
2983
|
throw new OwneyError(
|
|
@@ -3504,10 +3620,10 @@ var OwneySDK = class {
|
|
|
3504
3620
|
);
|
|
3505
3621
|
}
|
|
3506
3622
|
const provider = this.requireConnectedProvider();
|
|
3507
|
-
const wallet = (0,
|
|
3623
|
+
const wallet = (0, import_viem6.createWalletClient)({
|
|
3508
3624
|
account: state.walletAddress,
|
|
3509
3625
|
chain: VIEM_CHAIN2[chainId],
|
|
3510
|
-
transport: (0,
|
|
3626
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3511
3627
|
});
|
|
3512
3628
|
const hash = await wallet.writeContract({
|
|
3513
3629
|
address: token,
|
|
@@ -3517,9 +3633,9 @@ var OwneySDK = class {
|
|
|
3517
3633
|
account: state.walletAddress,
|
|
3518
3634
|
chain: VIEM_CHAIN2[chainId]
|
|
3519
3635
|
});
|
|
3520
|
-
const publicClient = (0,
|
|
3636
|
+
const publicClient = (0, import_viem6.createPublicClient)({
|
|
3521
3637
|
chain: VIEM_CHAIN2[chainId],
|
|
3522
|
-
transport: (0,
|
|
3638
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3523
3639
|
});
|
|
3524
3640
|
const receipt = await publicClient.waitForTransactionReceipt({
|
|
3525
3641
|
hash,
|
|
@@ -3628,7 +3744,7 @@ var OwneySDK = class {
|
|
|
3628
3744
|
};
|
|
3629
3745
|
|
|
3630
3746
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
3631
|
-
var
|
|
3747
|
+
var import_viem7 = require("viem");
|
|
3632
3748
|
var import_siwe = require("siwe");
|
|
3633
3749
|
var import_sdk2 = require("@zyfai/sdk");
|
|
3634
3750
|
|
|
@@ -3755,7 +3871,7 @@ function buildSIWXConfig(deps) {
|
|
|
3755
3871
|
issuedAt,
|
|
3756
3872
|
toString() {
|
|
3757
3873
|
return new import_siwe.SiweMessage({
|
|
3758
|
-
address: (0,
|
|
3874
|
+
address: (0, import_viem7.getAddress)(accountAddress),
|
|
3759
3875
|
chainId: numericChainId(chainId),
|
|
3760
3876
|
domain,
|
|
3761
3877
|
uri,
|
package/dist/index.d.cts
CHANGED
|
@@ -30,6 +30,17 @@ interface OwneySDKConfig {
|
|
|
30
30
|
* already-deployed app: set `globalThis.__OWNEY_DEBUG__ = true` in devtools.
|
|
31
31
|
*/
|
|
32
32
|
debug?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute URL of an ERC-7677 paymaster service. When set, deposits go out as
|
|
35
|
+
* an EIP-5792 `wallet_sendCalls` with `capabilities.paymasterService`, so a
|
|
36
|
+
* wallet that advertises sponsorship pays no native gas — the case EIP-3009
|
|
37
|
+
* cannot serve, because USDC verifies it with `ecrecover` and a smart account
|
|
38
|
+
* signs via ERC-1271.
|
|
39
|
+
*
|
|
40
|
+
* MUST be absolute: the wallet fetches this URL itself, so a relative path is
|
|
41
|
+
* unresolvable. Omit it and every rail behaves exactly as before.
|
|
42
|
+
*/
|
|
43
|
+
paymasterServiceUrl?: string;
|
|
33
44
|
}
|
|
34
45
|
interface ConnectionState {
|
|
35
46
|
provider: any;
|
|
@@ -418,6 +429,8 @@ declare class OwneySDK {
|
|
|
418
429
|
private referralSource?;
|
|
419
430
|
private cachedSponsoredCallback;
|
|
420
431
|
private cachedWethSponsoredCallback;
|
|
432
|
+
private paymasterServiceUrl?;
|
|
433
|
+
private cachedSponsoredCallsCallbacks;
|
|
421
434
|
private initializingAgentsPromise;
|
|
422
435
|
constructor(config: OwneySDKConfig);
|
|
423
436
|
/**
|
|
@@ -458,6 +471,13 @@ declare class OwneySDK {
|
|
|
458
471
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
459
472
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
460
473
|
*/
|
|
474
|
+
private getDefaultSponsoredCallsCallback;
|
|
475
|
+
/**
|
|
476
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
477
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
478
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
479
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
480
|
+
*/
|
|
461
481
|
private getDefaultWethSponsoredCallback;
|
|
462
482
|
private getAgent;
|
|
463
483
|
private getActiveAgents;
|
|
@@ -634,7 +654,7 @@ declare class OwneySDK {
|
|
|
634
654
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
635
655
|
}
|
|
636
656
|
|
|
637
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
657
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
638
658
|
declare class OwneyError extends Error {
|
|
639
659
|
readonly code: OwneyErrorCode;
|
|
640
660
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,17 @@ interface OwneySDKConfig {
|
|
|
30
30
|
* already-deployed app: set `globalThis.__OWNEY_DEBUG__ = true` in devtools.
|
|
31
31
|
*/
|
|
32
32
|
debug?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Absolute URL of an ERC-7677 paymaster service. When set, deposits go out as
|
|
35
|
+
* an EIP-5792 `wallet_sendCalls` with `capabilities.paymasterService`, so a
|
|
36
|
+
* wallet that advertises sponsorship pays no native gas — the case EIP-3009
|
|
37
|
+
* cannot serve, because USDC verifies it with `ecrecover` and a smart account
|
|
38
|
+
* signs via ERC-1271.
|
|
39
|
+
*
|
|
40
|
+
* MUST be absolute: the wallet fetches this URL itself, so a relative path is
|
|
41
|
+
* unresolvable. Omit it and every rail behaves exactly as before.
|
|
42
|
+
*/
|
|
43
|
+
paymasterServiceUrl?: string;
|
|
33
44
|
}
|
|
34
45
|
interface ConnectionState {
|
|
35
46
|
provider: any;
|
|
@@ -418,6 +429,8 @@ declare class OwneySDK {
|
|
|
418
429
|
private referralSource?;
|
|
419
430
|
private cachedSponsoredCallback;
|
|
420
431
|
private cachedWethSponsoredCallback;
|
|
432
|
+
private paymasterServiceUrl?;
|
|
433
|
+
private cachedSponsoredCallsCallbacks;
|
|
421
434
|
private initializingAgentsPromise;
|
|
422
435
|
constructor(config: OwneySDKConfig);
|
|
423
436
|
/**
|
|
@@ -458,6 +471,13 @@ declare class OwneySDK {
|
|
|
458
471
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
459
472
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
460
473
|
*/
|
|
474
|
+
private getDefaultSponsoredCallsCallback;
|
|
475
|
+
/**
|
|
476
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
477
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
478
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
479
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
480
|
+
*/
|
|
461
481
|
private getDefaultWethSponsoredCallback;
|
|
462
482
|
private getAgent;
|
|
463
483
|
private getActiveAgents;
|
|
@@ -634,7 +654,7 @@ declare class OwneySDK {
|
|
|
634
654
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
635
655
|
}
|
|
636
656
|
|
|
637
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
657
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "WALLET_NOT_DEPLOYED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "CHAIN_MISMATCH" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "DEPOSIT_INSUFFICIENT_BALANCE" | "WITHDRAW_NO_PERMITTED_TOKENS" | "WITHDRAW_INSUFFICIENT_BALANCE" | "WITHDRAW_ALL_FAILED" | "WITHDRAW_PARTIAL_FAILURE" | "WITHDRAW_FAILED" | "API_ROUTING_ERROR" | "API_ROUTING_FAILED" | "API_SAIL_ERROR" | "API_SAIL_TIMEOUT" | "API_NO_AGENTS" | "SPONSOR_REQUEST_FAILED" | "PERMIT2_APPROVAL_REQUIRED" | "SPONSORED_CALLS_UNSUPPORTED" | "SPONSORED_CALLS_NO_ID" | "SPONSORED_CALLS_NO_RECEIPT" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
638
658
|
declare class OwneyError extends Error {
|
|
639
659
|
readonly code: OwneyErrorCode;
|
|
640
660
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -2426,6 +2426,97 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2426
2426
|
};
|
|
2427
2427
|
}
|
|
2428
2428
|
|
|
2429
|
+
// src/lib/sponsored-calls-deposit.ts
|
|
2430
|
+
import { encodeFunctionData, erc20Abi, toHex } from "viem";
|
|
2431
|
+
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
2432
|
+
var DEFAULT_MAX_POLLS = 30;
|
|
2433
|
+
async function paymasterSupported(provider, owner, chainId) {
|
|
2434
|
+
const caps = await provider.request({
|
|
2435
|
+
method: "wallet_getCapabilities",
|
|
2436
|
+
params: [owner]
|
|
2437
|
+
});
|
|
2438
|
+
const forChain = caps?.[toHex(chainId)] ?? caps?.[String(chainId)];
|
|
2439
|
+
return Boolean(forChain?.paymasterService?.supported);
|
|
2440
|
+
}
|
|
2441
|
+
function makeSponsoredCallsCallback(deps) {
|
|
2442
|
+
const pollIntervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
2443
|
+
const maxPolls = deps.maxPolls ?? DEFAULT_MAX_POLLS;
|
|
2444
|
+
const absolutePaymasterUrl = () => {
|
|
2445
|
+
const configured = deps.paymasterServiceUrl;
|
|
2446
|
+
if (/^https?:\/\//i.test(configured)) return configured;
|
|
2447
|
+
const origin = globalThis.location?.origin;
|
|
2448
|
+
if (!origin) {
|
|
2449
|
+
throw new OwneyError(
|
|
2450
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2451
|
+
`paymasterServiceUrl "${configured}" is relative and no page origin is available to resolve it.`
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
return new URL(configured, origin).toString();
|
|
2455
|
+
};
|
|
2456
|
+
return async (smartWallet, chainId, amount) => {
|
|
2457
|
+
const cid = chainId;
|
|
2458
|
+
const token = deps.tokenAddressByChain[cid];
|
|
2459
|
+
if (!token) {
|
|
2460
|
+
throw new OwneyError(
|
|
2461
|
+
"CHAIN_UNSUPPORTED",
|
|
2462
|
+
`No sponsored token configured for chain ${chainId}`
|
|
2463
|
+
);
|
|
2464
|
+
}
|
|
2465
|
+
if (!await paymasterSupported(deps.provider, deps.ownerAddress, chainId)) {
|
|
2466
|
+
throw new OwneyError(
|
|
2467
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2468
|
+
`Wallet does not advertise paymasterService on chain ${chainId}.`,
|
|
2469
|
+
{ chainId }
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
const data = encodeFunctionData({
|
|
2473
|
+
abi: erc20Abi,
|
|
2474
|
+
functionName: "transfer",
|
|
2475
|
+
args: [smartWallet, BigInt(amount)]
|
|
2476
|
+
});
|
|
2477
|
+
const sendResult = await deps.provider.request({
|
|
2478
|
+
method: "wallet_sendCalls",
|
|
2479
|
+
params: [
|
|
2480
|
+
{
|
|
2481
|
+
version: "2.0.0",
|
|
2482
|
+
from: deps.ownerAddress,
|
|
2483
|
+
chainId: toHex(chainId),
|
|
2484
|
+
atomicRequired: false,
|
|
2485
|
+
calls: [{ to: token, value: "0x0", data }],
|
|
2486
|
+
capabilities: {
|
|
2487
|
+
paymasterService: { url: absolutePaymasterUrl() }
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2490
|
+
]
|
|
2491
|
+
});
|
|
2492
|
+
deps.onApproved?.();
|
|
2493
|
+
const callsId = typeof sendResult === "string" ? sendResult : sendResult?.id;
|
|
2494
|
+
if (!callsId) {
|
|
2495
|
+
throw new OwneyError(
|
|
2496
|
+
"SPONSORED_CALLS_NO_ID",
|
|
2497
|
+
"Wallet accepted wallet_sendCalls but returned no calls id.",
|
|
2498
|
+
{ chainId }
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
for (let attempt = 0; attempt < maxPolls; attempt += 1) {
|
|
2502
|
+
const status = await deps.provider.request({
|
|
2503
|
+
method: "wallet_getCallsStatus",
|
|
2504
|
+
params: [callsId]
|
|
2505
|
+
});
|
|
2506
|
+
const txHash = status?.receipts?.[0]?.transactionHash;
|
|
2507
|
+
if (txHash) return txHash;
|
|
2508
|
+
if (pollIntervalMs > 0) {
|
|
2509
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
throw new OwneyError(
|
|
2513
|
+
"SPONSORED_CALLS_NO_RECEIPT",
|
|
2514
|
+
`No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
|
|
2515
|
+
{ chainId, callsId }
|
|
2516
|
+
);
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2429
2520
|
// src/client.ts
|
|
2430
2521
|
function encodeMultiAgentCursor(map) {
|
|
2431
2522
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -2487,12 +2578,15 @@ var OwneySDK = class {
|
|
|
2487
2578
|
referralSource;
|
|
2488
2579
|
cachedSponsoredCallback = null;
|
|
2489
2580
|
cachedWethSponsoredCallback = null;
|
|
2581
|
+
paymasterServiceUrl;
|
|
2582
|
+
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2490
2583
|
initializingAgentsPromise = null;
|
|
2491
2584
|
constructor(config) {
|
|
2492
2585
|
this.apiKey = config.apiKey;
|
|
2493
2586
|
if (config.debug) setOwneyDebug(true);
|
|
2494
2587
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
2495
2588
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
2589
|
+
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
2496
2590
|
this.referralSource = config.referralSource;
|
|
2497
2591
|
}
|
|
2498
2592
|
/**
|
|
@@ -2515,6 +2609,7 @@ var OwneySDK = class {
|
|
|
2515
2609
|
this.state = { provider, walletAddress, chainId: null };
|
|
2516
2610
|
this.cachedSponsoredCallback = null;
|
|
2517
2611
|
this.cachedWethSponsoredCallback = null;
|
|
2612
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2518
2613
|
}
|
|
2519
2614
|
/**
|
|
2520
2615
|
* Disconnect from all agents and clear connection state.
|
|
@@ -2529,6 +2624,7 @@ var OwneySDK = class {
|
|
|
2529
2624
|
this.state = null;
|
|
2530
2625
|
this.cachedSponsoredCallback = null;
|
|
2531
2626
|
this.cachedWethSponsoredCallback = null;
|
|
2627
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2532
2628
|
}
|
|
2533
2629
|
isAgentDisabled(agentId) {
|
|
2534
2630
|
return this.disabledAgents.has(agentId);
|
|
@@ -2610,6 +2706,26 @@ var OwneySDK = class {
|
|
|
2610
2706
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2611
2707
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2612
2708
|
*/
|
|
2709
|
+
getDefaultSponsoredCallsCallback(asset, onApproved) {
|
|
2710
|
+
const cached = this.cachedSponsoredCallsCallbacks.get(asset);
|
|
2711
|
+
if (!onApproved && cached) return cached;
|
|
2712
|
+
const provider = this.requireConnectedProvider();
|
|
2713
|
+
const callback = makeSponsoredCallsCallback({
|
|
2714
|
+
provider,
|
|
2715
|
+
ownerAddress: this.state.walletAddress,
|
|
2716
|
+
paymasterServiceUrl: this.paymasterServiceUrl,
|
|
2717
|
+
onApproved,
|
|
2718
|
+
tokenAddressByChain: asset === "WETH" ? SPONSORED_WETH_BY_CHAIN : SPONSORED_USDC_BY_CHAIN
|
|
2719
|
+
});
|
|
2720
|
+
if (!onApproved) this.cachedSponsoredCallsCallbacks.set(asset, callback);
|
|
2721
|
+
return callback;
|
|
2722
|
+
}
|
|
2723
|
+
/**
|
|
2724
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
2725
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
2726
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2727
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2728
|
+
*/
|
|
2613
2729
|
getDefaultWethSponsoredCallback(onApproved) {
|
|
2614
2730
|
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
2615
2731
|
return this.cachedWethSponsoredCallback;
|
|
@@ -2832,7 +2948,7 @@ var OwneySDK = class {
|
|
|
2832
2948
|
}
|
|
2833
2949
|
const state = this.requireState();
|
|
2834
2950
|
const chainId = this.requireChainId();
|
|
2835
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2951
|
+
const effectiveCallback = depositCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2836
2952
|
if (agentId) {
|
|
2837
2953
|
if (this.isAgentDisabled(agentId)) {
|
|
2838
2954
|
throw new OwneyError(
|