@owney/sdk 0.7.7-beta.6 → 0.7.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/README.md +19 -0
- package/dist/index.cjs +172 -16
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +157 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,6 +263,25 @@ console.log(allEarnings.agentEarnings.zyfai.lifetimeEarnings); // 42.5
|
|
|
263
263
|
console.log(allEarnings.agentEarnings.zyfai.tokens); // per-chain, per-asset breakdown
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
+
### `refreshEarnings(agentId?)`
|
|
267
|
+
|
|
268
|
+
Refresh earnings for agents whose earnings data may be outdated. If the latest
|
|
269
|
+
snapshot is less than one hour old, the SDK returns it without recalculating.
|
|
270
|
+
|
|
271
|
+
| Param | Type | Description |
|
|
272
|
+
| --------- | -------------------- | ------------------------------------ |
|
|
273
|
+
| `agentId` | `"zyfai"` (optional) | Agent to refresh. Omit for all agents. |
|
|
274
|
+
|
|
275
|
+
Returns: `AgentEarnings` (single agent) or `OwneyEarnings` (all agents)
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// Single agent
|
|
279
|
+
const refreshed = await sdk.refreshEarnings("zyfai");
|
|
280
|
+
|
|
281
|
+
// All agents
|
|
282
|
+
const allRefreshed = await sdk.refreshEarnings();
|
|
283
|
+
```
|
|
284
|
+
|
|
266
285
|
### `getAccountApy({ agentId?, days })`
|
|
267
286
|
|
|
268
287
|
Get the weighted APY for the user's account. When querying all agents, the total APY is a balance-weighted average.
|
package/dist/index.cjs
CHANGED
|
@@ -871,6 +871,7 @@ var WETH_ADDRESS_BY_CHAIN = {
|
|
|
871
871
|
var VIEM_CHAIN = { 8453: import_chains.base, 42161: import_chains.arbitrum, 1: import_chains.mainnet };
|
|
872
872
|
var SPLITTING_ASSETS = ["USDC", "WETH"];
|
|
873
873
|
var POOL_POLICY_CHAIN_IDS = [8453, 42161, 1];
|
|
874
|
+
var EARNINGS_REFRESH_COOLDOWN_MS = 60 * 60 * 1e3;
|
|
874
875
|
var ZyfaiAgent = class {
|
|
875
876
|
id = "zyfai";
|
|
876
877
|
supportedChainIds = [8453, 42161, 1];
|
|
@@ -922,6 +923,7 @@ var ZyfaiAgent = class {
|
|
|
922
923
|
// successful decode is cached forever; failures are NOT cached so a transient
|
|
923
924
|
// RPC error retries on the next fetch.
|
|
924
925
|
withdrawAmountCache = /* @__PURE__ */ new Map();
|
|
926
|
+
earningsRefreshInFlight = null;
|
|
925
927
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
926
928
|
this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
|
|
927
929
|
this.sdk = new import_sdk.ZyfaiSDK({
|
|
@@ -1719,6 +1721,22 @@ var ZyfaiAgent = class {
|
|
|
1719
1721
|
const raw = await this.sdk.getOnchainEarnings(smartWallet);
|
|
1720
1722
|
return mapEarnings(raw, smartWallet);
|
|
1721
1723
|
}
|
|
1724
|
+
async refreshEarnings(state, chainId) {
|
|
1725
|
+
if (this.earningsRefreshInFlight) return this.earningsRefreshInFlight;
|
|
1726
|
+
this.earningsRefreshInFlight = (async () => {
|
|
1727
|
+
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1728
|
+
const current = await this.sdk.getOnchainEarnings(smartWallet);
|
|
1729
|
+
const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
|
|
1730
|
+
const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
|
|
1731
|
+
const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
|
|
1732
|
+
return mapEarnings(earnings, smartWallet);
|
|
1733
|
+
})();
|
|
1734
|
+
try {
|
|
1735
|
+
return await this.earningsRefreshInFlight;
|
|
1736
|
+
} finally {
|
|
1737
|
+
this.earningsRefreshInFlight = null;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1722
1740
|
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
1723
1741
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1724
1742
|
const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
|
|
@@ -2025,7 +2043,7 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
2025
2043
|
}
|
|
2026
2044
|
|
|
2027
2045
|
// src/client.ts
|
|
2028
|
-
var
|
|
2046
|
+
var import_viem6 = require("viem");
|
|
2029
2047
|
var import_chains2 = require("viem/chains");
|
|
2030
2048
|
|
|
2031
2049
|
// src/lib/transfer-auth.ts
|
|
@@ -2455,6 +2473,97 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2455
2473
|
};
|
|
2456
2474
|
}
|
|
2457
2475
|
|
|
2476
|
+
// src/lib/sponsored-calls-deposit.ts
|
|
2477
|
+
var import_viem5 = require("viem");
|
|
2478
|
+
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
2479
|
+
var DEFAULT_MAX_POLLS = 30;
|
|
2480
|
+
async function paymasterSupported(provider, owner, chainId) {
|
|
2481
|
+
const caps = await provider.request({
|
|
2482
|
+
method: "wallet_getCapabilities",
|
|
2483
|
+
params: [owner]
|
|
2484
|
+
});
|
|
2485
|
+
const forChain = caps?.[(0, import_viem5.toHex)(chainId)] ?? caps?.[String(chainId)];
|
|
2486
|
+
return Boolean(forChain?.paymasterService?.supported);
|
|
2487
|
+
}
|
|
2488
|
+
function makeSponsoredCallsCallback(deps) {
|
|
2489
|
+
const pollIntervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
2490
|
+
const maxPolls = deps.maxPolls ?? DEFAULT_MAX_POLLS;
|
|
2491
|
+
const absolutePaymasterUrl = () => {
|
|
2492
|
+
const configured = deps.paymasterServiceUrl;
|
|
2493
|
+
if (/^https?:\/\//i.test(configured)) return configured;
|
|
2494
|
+
const origin = globalThis.location?.origin;
|
|
2495
|
+
if (!origin) {
|
|
2496
|
+
throw new OwneyError(
|
|
2497
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2498
|
+
`paymasterServiceUrl "${configured}" is relative and no page origin is available to resolve it.`
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
return new URL(configured, origin).toString();
|
|
2502
|
+
};
|
|
2503
|
+
return async (smartWallet, chainId, amount) => {
|
|
2504
|
+
const cid = chainId;
|
|
2505
|
+
const token = deps.tokenAddressByChain[cid];
|
|
2506
|
+
if (!token) {
|
|
2507
|
+
throw new OwneyError(
|
|
2508
|
+
"CHAIN_UNSUPPORTED",
|
|
2509
|
+
`No sponsored token configured for chain ${chainId}`
|
|
2510
|
+
);
|
|
2511
|
+
}
|
|
2512
|
+
if (!await paymasterSupported(deps.provider, deps.ownerAddress, chainId)) {
|
|
2513
|
+
throw new OwneyError(
|
|
2514
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2515
|
+
`Wallet does not advertise paymasterService on chain ${chainId}.`,
|
|
2516
|
+
{ chainId }
|
|
2517
|
+
);
|
|
2518
|
+
}
|
|
2519
|
+
const data = (0, import_viem5.encodeFunctionData)({
|
|
2520
|
+
abi: import_viem5.erc20Abi,
|
|
2521
|
+
functionName: "transfer",
|
|
2522
|
+
args: [smartWallet, BigInt(amount)]
|
|
2523
|
+
});
|
|
2524
|
+
const sendResult = await deps.provider.request({
|
|
2525
|
+
method: "wallet_sendCalls",
|
|
2526
|
+
params: [
|
|
2527
|
+
{
|
|
2528
|
+
version: "2.0.0",
|
|
2529
|
+
from: deps.ownerAddress,
|
|
2530
|
+
chainId: (0, import_viem5.toHex)(chainId),
|
|
2531
|
+
atomicRequired: false,
|
|
2532
|
+
calls: [{ to: token, value: "0x0", data }],
|
|
2533
|
+
capabilities: {
|
|
2534
|
+
paymasterService: { url: absolutePaymasterUrl() }
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
]
|
|
2538
|
+
});
|
|
2539
|
+
deps.onApproved?.();
|
|
2540
|
+
const callsId = typeof sendResult === "string" ? sendResult : sendResult?.id;
|
|
2541
|
+
if (!callsId) {
|
|
2542
|
+
throw new OwneyError(
|
|
2543
|
+
"SPONSORED_CALLS_NO_ID",
|
|
2544
|
+
"Wallet accepted wallet_sendCalls but returned no calls id.",
|
|
2545
|
+
{ chainId }
|
|
2546
|
+
);
|
|
2547
|
+
}
|
|
2548
|
+
for (let attempt = 0; attempt < maxPolls; attempt += 1) {
|
|
2549
|
+
const status = await deps.provider.request({
|
|
2550
|
+
method: "wallet_getCallsStatus",
|
|
2551
|
+
params: [callsId]
|
|
2552
|
+
});
|
|
2553
|
+
const txHash = status?.receipts?.[0]?.transactionHash;
|
|
2554
|
+
if (txHash) return txHash;
|
|
2555
|
+
if (pollIntervalMs > 0) {
|
|
2556
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
throw new OwneyError(
|
|
2560
|
+
"SPONSORED_CALLS_NO_RECEIPT",
|
|
2561
|
+
`No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
|
|
2562
|
+
{ chainId, callsId }
|
|
2563
|
+
);
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
|
|
2458
2567
|
// src/client.ts
|
|
2459
2568
|
function encodeMultiAgentCursor(map) {
|
|
2460
2569
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -2516,12 +2625,15 @@ var OwneySDK = class {
|
|
|
2516
2625
|
referralSource;
|
|
2517
2626
|
cachedSponsoredCallback = null;
|
|
2518
2627
|
cachedWethSponsoredCallback = null;
|
|
2628
|
+
paymasterServiceUrl;
|
|
2629
|
+
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2519
2630
|
initializingAgentsPromise = null;
|
|
2520
2631
|
constructor(config) {
|
|
2521
2632
|
this.apiKey = config.apiKey;
|
|
2522
2633
|
if (config.debug) setOwneyDebug(true);
|
|
2523
2634
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
2524
2635
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
2636
|
+
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
2525
2637
|
this.referralSource = config.referralSource;
|
|
2526
2638
|
}
|
|
2527
2639
|
/**
|
|
@@ -2544,6 +2656,7 @@ var OwneySDK = class {
|
|
|
2544
2656
|
this.state = { provider, walletAddress, chainId: null };
|
|
2545
2657
|
this.cachedSponsoredCallback = null;
|
|
2546
2658
|
this.cachedWethSponsoredCallback = null;
|
|
2659
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2547
2660
|
}
|
|
2548
2661
|
/**
|
|
2549
2662
|
* Disconnect from all agents and clear connection state.
|
|
@@ -2558,6 +2671,7 @@ var OwneySDK = class {
|
|
|
2558
2671
|
this.state = null;
|
|
2559
2672
|
this.cachedSponsoredCallback = null;
|
|
2560
2673
|
this.cachedWethSponsoredCallback = null;
|
|
2674
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2561
2675
|
}
|
|
2562
2676
|
isAgentDisabled(agentId) {
|
|
2563
2677
|
return this.disabledAgents.has(agentId);
|
|
@@ -2620,14 +2734,14 @@ var OwneySDK = class {
|
|
|
2620
2734
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
2621
2735
|
// PublicClient/WalletClient param types — structurally identical at
|
|
2622
2736
|
// runtime, but the two share a name TS treats as unrelated.
|
|
2623
|
-
getPublicClient: (cid) => (0,
|
|
2737
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
2624
2738
|
chain: VIEM_CHAIN2[cid],
|
|
2625
|
-
transport: (0,
|
|
2739
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2626
2740
|
}),
|
|
2627
|
-
getWalletClient: (cid) => (0,
|
|
2741
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
2628
2742
|
account: owner,
|
|
2629
2743
|
chain: VIEM_CHAIN2[cid],
|
|
2630
|
-
transport: (0,
|
|
2744
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2631
2745
|
})
|
|
2632
2746
|
});
|
|
2633
2747
|
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
@@ -2639,6 +2753,26 @@ var OwneySDK = class {
|
|
|
2639
2753
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2640
2754
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2641
2755
|
*/
|
|
2756
|
+
getDefaultSponsoredCallsCallback(asset, onApproved) {
|
|
2757
|
+
const cached = this.cachedSponsoredCallsCallbacks.get(asset);
|
|
2758
|
+
if (!onApproved && cached) return cached;
|
|
2759
|
+
const provider = this.requireConnectedProvider();
|
|
2760
|
+
const callback = makeSponsoredCallsCallback({
|
|
2761
|
+
provider,
|
|
2762
|
+
ownerAddress: this.state.walletAddress,
|
|
2763
|
+
paymasterServiceUrl: this.paymasterServiceUrl,
|
|
2764
|
+
onApproved,
|
|
2765
|
+
tokenAddressByChain: asset === "WETH" ? SPONSORED_WETH_BY_CHAIN : SPONSORED_USDC_BY_CHAIN
|
|
2766
|
+
});
|
|
2767
|
+
if (!onApproved) this.cachedSponsoredCallsCallbacks.set(asset, callback);
|
|
2768
|
+
return callback;
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
2772
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
2773
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2774
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2775
|
+
*/
|
|
2642
2776
|
getDefaultWethSponsoredCallback(onApproved) {
|
|
2643
2777
|
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
2644
2778
|
return this.cachedWethSponsoredCallback;
|
|
@@ -2653,14 +2787,14 @@ var OwneySDK = class {
|
|
|
2653
2787
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
2654
2788
|
// PublicClient/WalletClient param types — structurally identical at
|
|
2655
2789
|
// runtime, but the two share a name TS treats as unrelated.
|
|
2656
|
-
getPublicClient: (cid) => (0,
|
|
2790
|
+
getPublicClient: (cid) => (0, import_viem6.createPublicClient)({
|
|
2657
2791
|
chain: VIEM_CHAIN2[cid],
|
|
2658
|
-
transport: (0,
|
|
2792
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2659
2793
|
}),
|
|
2660
|
-
getWalletClient: (cid) => (0,
|
|
2794
|
+
getWalletClient: (cid) => (0, import_viem6.createWalletClient)({
|
|
2661
2795
|
account: owner,
|
|
2662
2796
|
chain: VIEM_CHAIN2[cid],
|
|
2663
|
-
transport: (0,
|
|
2797
|
+
transport: (0, import_viem6.custom)(provider)
|
|
2664
2798
|
})
|
|
2665
2799
|
});
|
|
2666
2800
|
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
@@ -2861,7 +2995,7 @@ var OwneySDK = class {
|
|
|
2861
2995
|
}
|
|
2862
2996
|
const state = this.requireState();
|
|
2863
2997
|
const chainId = this.requireChainId();
|
|
2864
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2998
|
+
const effectiveCallback = depositCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2865
2999
|
if (agentId) {
|
|
2866
3000
|
if (this.isAgentDisabled(agentId)) {
|
|
2867
3001
|
throw new OwneyError(
|
|
@@ -3303,6 +3437,28 @@ var OwneySDK = class {
|
|
|
3303
3437
|
agentEarnings: results
|
|
3304
3438
|
};
|
|
3305
3439
|
}
|
|
3440
|
+
/**
|
|
3441
|
+
* Return refreshed earnings while letting each agent own its refresh policy.
|
|
3442
|
+
* Agents without a refresh capability fall back to their current snapshot.
|
|
3443
|
+
*/
|
|
3444
|
+
async refreshEarnings(agentId) {
|
|
3445
|
+
const state = this.requireState();
|
|
3446
|
+
const chainId = this.requireChainId();
|
|
3447
|
+
const refreshAgent = (agent) => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId);
|
|
3448
|
+
if (agentId) return refreshAgent(this.getAgent(agentId));
|
|
3449
|
+
let totalEarnings = 0;
|
|
3450
|
+
const agentEarnings = {};
|
|
3451
|
+
const refreshed = await Promise.all(
|
|
3452
|
+
[...this.getActiveAgents().entries()].map(
|
|
3453
|
+
async ([id, agent]) => [id, await refreshAgent(agent)]
|
|
3454
|
+
)
|
|
3455
|
+
);
|
|
3456
|
+
for (const [id, earnings] of refreshed) {
|
|
3457
|
+
agentEarnings[id] = earnings;
|
|
3458
|
+
totalEarnings += Number(earnings.lifetimeEarnings);
|
|
3459
|
+
}
|
|
3460
|
+
return { totalEarnings: String(totalEarnings), agentEarnings };
|
|
3461
|
+
}
|
|
3306
3462
|
/**
|
|
3307
3463
|
* Get the weighted APY for the user's account over a time period.
|
|
3308
3464
|
* When querying all agents, the total APY is a balance-weighted average.
|
|
@@ -3504,10 +3660,10 @@ var OwneySDK = class {
|
|
|
3504
3660
|
);
|
|
3505
3661
|
}
|
|
3506
3662
|
const provider = this.requireConnectedProvider();
|
|
3507
|
-
const wallet = (0,
|
|
3663
|
+
const wallet = (0, import_viem6.createWalletClient)({
|
|
3508
3664
|
account: state.walletAddress,
|
|
3509
3665
|
chain: VIEM_CHAIN2[chainId],
|
|
3510
|
-
transport: (0,
|
|
3666
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3511
3667
|
});
|
|
3512
3668
|
const hash = await wallet.writeContract({
|
|
3513
3669
|
address: token,
|
|
@@ -3517,9 +3673,9 @@ var OwneySDK = class {
|
|
|
3517
3673
|
account: state.walletAddress,
|
|
3518
3674
|
chain: VIEM_CHAIN2[chainId]
|
|
3519
3675
|
});
|
|
3520
|
-
const publicClient = (0,
|
|
3676
|
+
const publicClient = (0, import_viem6.createPublicClient)({
|
|
3521
3677
|
chain: VIEM_CHAIN2[chainId],
|
|
3522
|
-
transport: (0,
|
|
3678
|
+
transport: (0, import_viem6.custom)(provider)
|
|
3523
3679
|
});
|
|
3524
3680
|
const receipt = await publicClient.waitForTransactionReceipt({
|
|
3525
3681
|
hash,
|
|
@@ -3628,7 +3784,7 @@ var OwneySDK = class {
|
|
|
3628
3784
|
};
|
|
3629
3785
|
|
|
3630
3786
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
3631
|
-
var
|
|
3787
|
+
var import_viem7 = require("viem");
|
|
3632
3788
|
var import_siwe = require("siwe");
|
|
3633
3789
|
var import_sdk2 = require("@zyfai/sdk");
|
|
3634
3790
|
|
|
@@ -3755,7 +3911,7 @@ function buildSIWXConfig(deps) {
|
|
|
3755
3911
|
issuedAt,
|
|
3756
3912
|
toString() {
|
|
3757
3913
|
return new import_siwe.SiweMessage({
|
|
3758
|
-
address: (0,
|
|
3914
|
+
address: (0, import_viem7.getAddress)(accountAddress),
|
|
3759
3915
|
chainId: numericChainId(chainId),
|
|
3760
3916
|
domain,
|
|
3761
3917
|
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;
|
|
@@ -372,6 +383,11 @@ interface IAgent {
|
|
|
372
383
|
withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
|
|
373
384
|
getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
|
|
374
385
|
getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
|
|
386
|
+
/**
|
|
387
|
+
* Refresh the agent's earnings snapshot when its backend supports doing so.
|
|
388
|
+
* Implementations own freshness and request-deduplication policy.
|
|
389
|
+
*/
|
|
390
|
+
refreshEarnings?(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
|
|
375
391
|
getAccountApy(state: ConnectionState, chainId: number, days: DailyApyDays,
|
|
376
392
|
/**
|
|
377
393
|
* Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
|
|
@@ -418,6 +434,8 @@ declare class OwneySDK {
|
|
|
418
434
|
private referralSource?;
|
|
419
435
|
private cachedSponsoredCallback;
|
|
420
436
|
private cachedWethSponsoredCallback;
|
|
437
|
+
private paymasterServiceUrl?;
|
|
438
|
+
private cachedSponsoredCallsCallbacks;
|
|
421
439
|
private initializingAgentsPromise;
|
|
422
440
|
constructor(config: OwneySDKConfig);
|
|
423
441
|
/**
|
|
@@ -458,6 +476,13 @@ declare class OwneySDK {
|
|
|
458
476
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
459
477
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
460
478
|
*/
|
|
479
|
+
private getDefaultSponsoredCallsCallback;
|
|
480
|
+
/**
|
|
481
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
482
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
483
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
484
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
485
|
+
*/
|
|
461
486
|
private getDefaultWethSponsoredCallback;
|
|
462
487
|
private getAgent;
|
|
463
488
|
private getActiveAgents;
|
|
@@ -561,6 +586,11 @@ declare class OwneySDK {
|
|
|
561
586
|
* @returns {AgentEarnings} for a single agent, or {OwneyEarnings} with totalEarnings and per-agent breakdown
|
|
562
587
|
*/
|
|
563
588
|
getEarnings(agentId?: AgentId): Promise<OwneyEarnings | AgentEarnings>;
|
|
589
|
+
/**
|
|
590
|
+
* Return refreshed earnings while letting each agent own its refresh policy.
|
|
591
|
+
* Agents without a refresh capability fall back to their current snapshot.
|
|
592
|
+
*/
|
|
593
|
+
refreshEarnings(agentId?: AgentId): Promise<OwneyEarnings | AgentEarnings>;
|
|
564
594
|
/**
|
|
565
595
|
* Get the weighted APY for the user's account over a time period.
|
|
566
596
|
* When querying all agents, the total APY is a balance-weighted average.
|
|
@@ -634,7 +664,7 @@ declare class OwneySDK {
|
|
|
634
664
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
635
665
|
}
|
|
636
666
|
|
|
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";
|
|
667
|
+
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
668
|
declare class OwneyError extends Error {
|
|
639
669
|
readonly code: OwneyErrorCode;
|
|
640
670
|
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;
|
|
@@ -372,6 +383,11 @@ interface IAgent {
|
|
|
372
383
|
withdraw(state: ConnectionState, chainId: number, token: OwneySupportedTokens, amount?: string): Promise<AgentWithdrawResult>;
|
|
373
384
|
getBalances(state: ConnectionState, chainId: number): Promise<AgentBalance>;
|
|
374
385
|
getEarnings(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
|
|
386
|
+
/**
|
|
387
|
+
* Refresh the agent's earnings snapshot when its backend supports doing so.
|
|
388
|
+
* Implementations own freshness and request-deduplication policy.
|
|
389
|
+
*/
|
|
390
|
+
refreshEarnings?(state: ConnectionState, chainId: number): Promise<AgentEarnings>;
|
|
375
391
|
getAccountApy(state: ConnectionState, chainId: number, days: DailyApyDays,
|
|
376
392
|
/**
|
|
377
393
|
* Optional asset symbol ("USDC" / "WETH") scoping the daily series to a
|
|
@@ -418,6 +434,8 @@ declare class OwneySDK {
|
|
|
418
434
|
private referralSource?;
|
|
419
435
|
private cachedSponsoredCallback;
|
|
420
436
|
private cachedWethSponsoredCallback;
|
|
437
|
+
private paymasterServiceUrl?;
|
|
438
|
+
private cachedSponsoredCallsCallbacks;
|
|
421
439
|
private initializingAgentsPromise;
|
|
422
440
|
constructor(config: OwneySDKConfig);
|
|
423
441
|
/**
|
|
@@ -458,6 +476,13 @@ declare class OwneySDK {
|
|
|
458
476
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
459
477
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
460
478
|
*/
|
|
479
|
+
private getDefaultSponsoredCallsCallback;
|
|
480
|
+
/**
|
|
481
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
482
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
483
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
484
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
485
|
+
*/
|
|
461
486
|
private getDefaultWethSponsoredCallback;
|
|
462
487
|
private getAgent;
|
|
463
488
|
private getActiveAgents;
|
|
@@ -561,6 +586,11 @@ declare class OwneySDK {
|
|
|
561
586
|
* @returns {AgentEarnings} for a single agent, or {OwneyEarnings} with totalEarnings and per-agent breakdown
|
|
562
587
|
*/
|
|
563
588
|
getEarnings(agentId?: AgentId): Promise<OwneyEarnings | AgentEarnings>;
|
|
589
|
+
/**
|
|
590
|
+
* Return refreshed earnings while letting each agent own its refresh policy.
|
|
591
|
+
* Agents without a refresh capability fall back to their current snapshot.
|
|
592
|
+
*/
|
|
593
|
+
refreshEarnings(agentId?: AgentId): Promise<OwneyEarnings | AgentEarnings>;
|
|
564
594
|
/**
|
|
565
595
|
* Get the weighted APY for the user's account over a time period.
|
|
566
596
|
* When querying all agents, the total APY is a balance-weighted average.
|
|
@@ -634,7 +664,7 @@ declare class OwneySDK {
|
|
|
634
664
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
635
665
|
}
|
|
636
666
|
|
|
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";
|
|
667
|
+
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
668
|
declare class OwneyError extends Error {
|
|
639
669
|
readonly code: OwneyErrorCode;
|
|
640
670
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -838,6 +838,7 @@ var WETH_ADDRESS_BY_CHAIN = {
|
|
|
838
838
|
var VIEM_CHAIN = { 8453: base, 42161: arbitrum, 1: mainnet };
|
|
839
839
|
var SPLITTING_ASSETS = ["USDC", "WETH"];
|
|
840
840
|
var POOL_POLICY_CHAIN_IDS = [8453, 42161, 1];
|
|
841
|
+
var EARNINGS_REFRESH_COOLDOWN_MS = 60 * 60 * 1e3;
|
|
841
842
|
var ZyfaiAgent = class {
|
|
842
843
|
id = "zyfai";
|
|
843
844
|
supportedChainIds = [8453, 42161, 1];
|
|
@@ -889,6 +890,7 @@ var ZyfaiAgent = class {
|
|
|
889
890
|
// successful decode is cached forever; failures are NOT cached so a transient
|
|
890
891
|
// RPC error retries on the next fetch.
|
|
891
892
|
withdrawAmountCache = /* @__PURE__ */ new Map();
|
|
893
|
+
earningsRefreshInFlight = null;
|
|
892
894
|
constructor(apiKey, rpcUrls, referralSource) {
|
|
893
895
|
this.rpcUrls = rpcUrls ?? DEFAULT_ZYFAI_RPC_URLS;
|
|
894
896
|
this.sdk = new ZyfaiSDK({
|
|
@@ -1686,6 +1688,22 @@ var ZyfaiAgent = class {
|
|
|
1686
1688
|
const raw = await this.sdk.getOnchainEarnings(smartWallet);
|
|
1687
1689
|
return mapEarnings(raw, smartWallet);
|
|
1688
1690
|
}
|
|
1691
|
+
async refreshEarnings(state, chainId) {
|
|
1692
|
+
if (this.earningsRefreshInFlight) return this.earningsRefreshInFlight;
|
|
1693
|
+
this.earningsRefreshInFlight = (async () => {
|
|
1694
|
+
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1695
|
+
const current = await this.sdk.getOnchainEarnings(smartWallet);
|
|
1696
|
+
const lastCheck = current.data.lastCheckTimestamp ? Date.parse(current.data.lastCheckTimestamp) : Number.NaN;
|
|
1697
|
+
const isFresh = Number.isFinite(lastCheck) && Date.now() - lastCheck < EARNINGS_REFRESH_COOLDOWN_MS;
|
|
1698
|
+
const earnings = isFresh ? current : await this.sdk.calculateOnchainEarnings(smartWallet);
|
|
1699
|
+
return mapEarnings(earnings, smartWallet);
|
|
1700
|
+
})();
|
|
1701
|
+
try {
|
|
1702
|
+
return await this.earningsRefreshInFlight;
|
|
1703
|
+
} finally {
|
|
1704
|
+
this.earningsRefreshInFlight = null;
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1689
1707
|
async getAccountApy(state, chainId, days, tokenSymbol) {
|
|
1690
1708
|
const { smartWallet } = await this.resolveSmartWallet(state, chainId);
|
|
1691
1709
|
const raw = await this.sdk.getDailyApyHistory(smartWallet, days);
|
|
@@ -2426,6 +2444,97 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2426
2444
|
};
|
|
2427
2445
|
}
|
|
2428
2446
|
|
|
2447
|
+
// src/lib/sponsored-calls-deposit.ts
|
|
2448
|
+
import { encodeFunctionData, erc20Abi, toHex } from "viem";
|
|
2449
|
+
var DEFAULT_POLL_INTERVAL_MS = 1500;
|
|
2450
|
+
var DEFAULT_MAX_POLLS = 30;
|
|
2451
|
+
async function paymasterSupported(provider, owner, chainId) {
|
|
2452
|
+
const caps = await provider.request({
|
|
2453
|
+
method: "wallet_getCapabilities",
|
|
2454
|
+
params: [owner]
|
|
2455
|
+
});
|
|
2456
|
+
const forChain = caps?.[toHex(chainId)] ?? caps?.[String(chainId)];
|
|
2457
|
+
return Boolean(forChain?.paymasterService?.supported);
|
|
2458
|
+
}
|
|
2459
|
+
function makeSponsoredCallsCallback(deps) {
|
|
2460
|
+
const pollIntervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
2461
|
+
const maxPolls = deps.maxPolls ?? DEFAULT_MAX_POLLS;
|
|
2462
|
+
const absolutePaymasterUrl = () => {
|
|
2463
|
+
const configured = deps.paymasterServiceUrl;
|
|
2464
|
+
if (/^https?:\/\//i.test(configured)) return configured;
|
|
2465
|
+
const origin = globalThis.location?.origin;
|
|
2466
|
+
if (!origin) {
|
|
2467
|
+
throw new OwneyError(
|
|
2468
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2469
|
+
`paymasterServiceUrl "${configured}" is relative and no page origin is available to resolve it.`
|
|
2470
|
+
);
|
|
2471
|
+
}
|
|
2472
|
+
return new URL(configured, origin).toString();
|
|
2473
|
+
};
|
|
2474
|
+
return async (smartWallet, chainId, amount) => {
|
|
2475
|
+
const cid = chainId;
|
|
2476
|
+
const token = deps.tokenAddressByChain[cid];
|
|
2477
|
+
if (!token) {
|
|
2478
|
+
throw new OwneyError(
|
|
2479
|
+
"CHAIN_UNSUPPORTED",
|
|
2480
|
+
`No sponsored token configured for chain ${chainId}`
|
|
2481
|
+
);
|
|
2482
|
+
}
|
|
2483
|
+
if (!await paymasterSupported(deps.provider, deps.ownerAddress, chainId)) {
|
|
2484
|
+
throw new OwneyError(
|
|
2485
|
+
"SPONSORED_CALLS_UNSUPPORTED",
|
|
2486
|
+
`Wallet does not advertise paymasterService on chain ${chainId}.`,
|
|
2487
|
+
{ chainId }
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
const data = encodeFunctionData({
|
|
2491
|
+
abi: erc20Abi,
|
|
2492
|
+
functionName: "transfer",
|
|
2493
|
+
args: [smartWallet, BigInt(amount)]
|
|
2494
|
+
});
|
|
2495
|
+
const sendResult = await deps.provider.request({
|
|
2496
|
+
method: "wallet_sendCalls",
|
|
2497
|
+
params: [
|
|
2498
|
+
{
|
|
2499
|
+
version: "2.0.0",
|
|
2500
|
+
from: deps.ownerAddress,
|
|
2501
|
+
chainId: toHex(chainId),
|
|
2502
|
+
atomicRequired: false,
|
|
2503
|
+
calls: [{ to: token, value: "0x0", data }],
|
|
2504
|
+
capabilities: {
|
|
2505
|
+
paymasterService: { url: absolutePaymasterUrl() }
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
]
|
|
2509
|
+
});
|
|
2510
|
+
deps.onApproved?.();
|
|
2511
|
+
const callsId = typeof sendResult === "string" ? sendResult : sendResult?.id;
|
|
2512
|
+
if (!callsId) {
|
|
2513
|
+
throw new OwneyError(
|
|
2514
|
+
"SPONSORED_CALLS_NO_ID",
|
|
2515
|
+
"Wallet accepted wallet_sendCalls but returned no calls id.",
|
|
2516
|
+
{ chainId }
|
|
2517
|
+
);
|
|
2518
|
+
}
|
|
2519
|
+
for (let attempt = 0; attempt < maxPolls; attempt += 1) {
|
|
2520
|
+
const status = await deps.provider.request({
|
|
2521
|
+
method: "wallet_getCallsStatus",
|
|
2522
|
+
params: [callsId]
|
|
2523
|
+
});
|
|
2524
|
+
const txHash = status?.receipts?.[0]?.transactionHash;
|
|
2525
|
+
if (txHash) return txHash;
|
|
2526
|
+
if (pollIntervalMs > 0) {
|
|
2527
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2528
|
+
}
|
|
2529
|
+
}
|
|
2530
|
+
throw new OwneyError(
|
|
2531
|
+
"SPONSORED_CALLS_NO_RECEIPT",
|
|
2532
|
+
`No receipt for calls ${callsId} after ${maxPolls} polls; the deposit may still settle.`,
|
|
2533
|
+
{ chainId, callsId }
|
|
2534
|
+
);
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2429
2538
|
// src/client.ts
|
|
2430
2539
|
function encodeMultiAgentCursor(map) {
|
|
2431
2540
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -2487,12 +2596,15 @@ var OwneySDK = class {
|
|
|
2487
2596
|
referralSource;
|
|
2488
2597
|
cachedSponsoredCallback = null;
|
|
2489
2598
|
cachedWethSponsoredCallback = null;
|
|
2599
|
+
paymasterServiceUrl;
|
|
2600
|
+
cachedSponsoredCallsCallbacks = /* @__PURE__ */ new Map();
|
|
2490
2601
|
initializingAgentsPromise = null;
|
|
2491
2602
|
constructor(config) {
|
|
2492
2603
|
this.apiKey = config.apiKey;
|
|
2493
2604
|
if (config.debug) setOwneyDebug(true);
|
|
2494
2605
|
this.zyfaiRpcUrls = config.zyfaiRpcUrls;
|
|
2495
2606
|
this.routingApiBaseUrl = config.routingApiBaseUrl;
|
|
2607
|
+
this.paymasterServiceUrl = config.paymasterServiceUrl;
|
|
2496
2608
|
this.referralSource = config.referralSource;
|
|
2497
2609
|
}
|
|
2498
2610
|
/**
|
|
@@ -2515,6 +2627,7 @@ var OwneySDK = class {
|
|
|
2515
2627
|
this.state = { provider, walletAddress, chainId: null };
|
|
2516
2628
|
this.cachedSponsoredCallback = null;
|
|
2517
2629
|
this.cachedWethSponsoredCallback = null;
|
|
2630
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2518
2631
|
}
|
|
2519
2632
|
/**
|
|
2520
2633
|
* Disconnect from all agents and clear connection state.
|
|
@@ -2529,6 +2642,7 @@ var OwneySDK = class {
|
|
|
2529
2642
|
this.state = null;
|
|
2530
2643
|
this.cachedSponsoredCallback = null;
|
|
2531
2644
|
this.cachedWethSponsoredCallback = null;
|
|
2645
|
+
this.cachedSponsoredCallsCallbacks.clear();
|
|
2532
2646
|
}
|
|
2533
2647
|
isAgentDisabled(agentId) {
|
|
2534
2648
|
return this.disabledAgents.has(agentId);
|
|
@@ -2610,6 +2724,26 @@ var OwneySDK = class {
|
|
|
2610
2724
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2611
2725
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2612
2726
|
*/
|
|
2727
|
+
getDefaultSponsoredCallsCallback(asset, onApproved) {
|
|
2728
|
+
const cached = this.cachedSponsoredCallsCallbacks.get(asset);
|
|
2729
|
+
if (!onApproved && cached) return cached;
|
|
2730
|
+
const provider = this.requireConnectedProvider();
|
|
2731
|
+
const callback = makeSponsoredCallsCallback({
|
|
2732
|
+
provider,
|
|
2733
|
+
ownerAddress: this.state.walletAddress,
|
|
2734
|
+
paymasterServiceUrl: this.paymasterServiceUrl,
|
|
2735
|
+
onApproved,
|
|
2736
|
+
tokenAddressByChain: asset === "WETH" ? SPONSORED_WETH_BY_CHAIN : SPONSORED_USDC_BY_CHAIN
|
|
2737
|
+
});
|
|
2738
|
+
if (!onApproved) this.cachedSponsoredCallsCallbacks.set(asset, callback);
|
|
2739
|
+
return callback;
|
|
2740
|
+
}
|
|
2741
|
+
/**
|
|
2742
|
+
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
2743
|
+
* callback used when the caller omits `depositCallback` for a WETH deposit.
|
|
2744
|
+
* Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
2745
|
+
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
2746
|
+
*/
|
|
2613
2747
|
getDefaultWethSponsoredCallback(onApproved) {
|
|
2614
2748
|
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
2615
2749
|
return this.cachedWethSponsoredCallback;
|
|
@@ -2832,7 +2966,7 @@ var OwneySDK = class {
|
|
|
2832
2966
|
}
|
|
2833
2967
|
const state = this.requireState();
|
|
2834
2968
|
const chainId = this.requireChainId();
|
|
2835
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2969
|
+
const effectiveCallback = depositCallback ?? (this.paymasterServiceUrl ? this.getDefaultSponsoredCallsCallback(asset, onApproved) : asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2836
2970
|
if (agentId) {
|
|
2837
2971
|
if (this.isAgentDisabled(agentId)) {
|
|
2838
2972
|
throw new OwneyError(
|
|
@@ -3274,6 +3408,28 @@ var OwneySDK = class {
|
|
|
3274
3408
|
agentEarnings: results
|
|
3275
3409
|
};
|
|
3276
3410
|
}
|
|
3411
|
+
/**
|
|
3412
|
+
* Return refreshed earnings while letting each agent own its refresh policy.
|
|
3413
|
+
* Agents without a refresh capability fall back to their current snapshot.
|
|
3414
|
+
*/
|
|
3415
|
+
async refreshEarnings(agentId) {
|
|
3416
|
+
const state = this.requireState();
|
|
3417
|
+
const chainId = this.requireChainId();
|
|
3418
|
+
const refreshAgent = (agent) => agent.refreshEarnings?.(state, chainId) ?? agent.getEarnings(state, chainId);
|
|
3419
|
+
if (agentId) return refreshAgent(this.getAgent(agentId));
|
|
3420
|
+
let totalEarnings = 0;
|
|
3421
|
+
const agentEarnings = {};
|
|
3422
|
+
const refreshed = await Promise.all(
|
|
3423
|
+
[...this.getActiveAgents().entries()].map(
|
|
3424
|
+
async ([id, agent]) => [id, await refreshAgent(agent)]
|
|
3425
|
+
)
|
|
3426
|
+
);
|
|
3427
|
+
for (const [id, earnings] of refreshed) {
|
|
3428
|
+
agentEarnings[id] = earnings;
|
|
3429
|
+
totalEarnings += Number(earnings.lifetimeEarnings);
|
|
3430
|
+
}
|
|
3431
|
+
return { totalEarnings: String(totalEarnings), agentEarnings };
|
|
3432
|
+
}
|
|
3277
3433
|
/**
|
|
3278
3434
|
* Get the weighted APY for the user's account over a time period.
|
|
3279
3435
|
* When querying all agents, the total APY is a balance-weighted average.
|