@owney/sdk 0.7.22-beta.1 → 0.7.23-beta.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owney/sdk",
3
- "version": "0.7.22-beta.1",
3
+ "version": "0.7.23-beta.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
@@ -20,12 +20,10 @@
20
20
  "build": "tsup",
21
21
  "dev": "tsup --watch",
22
22
  "test": "vitest run",
23
- "test:watch": "vitest",
24
- "typecheck": "tsc -p tsconfig.test.json --noEmit"
23
+ "test:watch": "vitest"
25
24
  },
26
25
  "dependencies": {
27
- "@zyfai/sdk": "0.2.52",
28
- "permissionless": "^0.4.0",
26
+ "@zyfai/sdk": "0.2.55",
29
27
  "siwe": "^3.0.0",
30
28
  "viem": "^2.48.1"
31
29
  },
@@ -1,283 +0,0 @@
1
- import {
2
- buildPermitTypedData
3
- } from "./chunk-AURO3C3R.js";
4
-
5
- // src/agents/surfliquid/surfliquid.constants.ts
6
- var SURFLIQUID_CHAIN_ID = 8453;
7
- var SURFLIQUID_CHAIN_NAME = "BASE";
8
- var SURFLIQUID_USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
9
- var SURFLIQUID_PERMIT_CAP = 10000000000n;
10
- var SURFLIQUID_PERMIT_TTL_SECONDS = 3600n;
11
- var SURFLIQUID_MIN_DEPOSIT = "0";
12
- var SURFLIQUID_SUPPORTED_ASSETS = [
13
- {
14
- chainId: SURFLIQUID_CHAIN_ID,
15
- chain: SURFLIQUID_CHAIN_NAME,
16
- assets: [{ symbol: "USDC", minDepositAmount: SURFLIQUID_MIN_DEPOSIT }]
17
- }
18
- ];
19
- var SURFLIQUID_ACTION_MAP = {
20
- // INITIAL_DEPOSIT is the user's real first deposit, so surface it like any
21
- // other funding ("Top up"). The mini-app intentionally hides the "Deposit"
22
- // action (it marks Zyfai's smart-account-creation event), which would
23
- // otherwise drop a SurfLiquid user's only history row.
24
- INITIAL_DEPOSIT: "Top up",
25
- DEPOSIT: "Top up",
26
- USER_DEPOSIT: "Top up",
27
- WITHDRAWAL: "Withdraw",
28
- USER_WITHDRAWAL: "Withdraw",
29
- REBALANCE: "Rebalance",
30
- REBALANCE_COMPLETED: "Rebalance",
31
- CROSS_CHAIN_REBALANCE: "Rebalance",
32
- MERKL_CLAIM: "Earned"
33
- };
34
-
35
- // src/agents/surfliquid/surfliquid.contracts.ts
36
- import { parseAbi } from "viem";
37
- var SURFLIQUID_FACTORY_ADDRESS = "0x8fa50DeA8DB10987D7d22ac092001c3613C18779";
38
- var SURFLIQUID_FACTORY_ABI = parseAbi([
39
- "function deployVault(address vaultOwner, bytes32 salt) returns (address)",
40
- "function computeVaultAddress(address vaultOwner, bytes32 salt) view returns (address)"
41
- ]);
42
- var SURFLIQUID_VAULT_ABI = parseAbi([
43
- "function initialDeposit(address asset, address vault, uint256 amount)",
44
- "function userDeposit(address asset, uint256 amount)",
45
- // amount 0 withdraws everything; proceeds go to the vault's owner.
46
- "function withdraw(address asset, uint256 amount)",
47
- "function assetHasInitialDeposit(address asset) view returns (bool)",
48
- "function owner() view returns (address)"
49
- ]);
50
- var USDC_ABI = parseAbi([
51
- "function approve(address spender, uint256 amount)",
52
- "function transfer(address to, uint256 amount)",
53
- "function transferFrom(address from, address to, uint256 value)",
54
- "function balanceOf(address account) view returns (uint256)",
55
- "function allowance(address owner, address spender) view returns (uint256)",
56
- "function nonces(address owner) view returns (uint256)",
57
- "function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)"
58
- ]);
59
-
60
- // src/agents/surfliquid/surfliquid.sponsorship.ts
61
- import { parseSignature } from "viem";
62
-
63
- // src/agents/surfliquid/surfliquid.calls.ts
64
- import { encodeFunctionData } from "viem";
65
- var call = (to, abi, functionName, args) => ({
66
- to,
67
- data: encodeFunctionData({ abi, functionName, args })
68
- });
69
- function buildDepositCalls(input) {
70
- const { smartAccount, owner, vault, amount, permit, deploySalt } = input;
71
- if (permit && permit.owner.toLowerCase() !== owner.toLowerCase()) {
72
- throw new Error("Permit must be signed by the smart account's owner");
73
- }
74
- if (permit && permit.value < amount) {
75
- throw new Error("Permit allowance is worth less than the deposit");
76
- }
77
- if (!input.hasInitialDeposit && !input.morphoVault) {
78
- throw new Error("A first deposit needs a target morpho vault");
79
- }
80
- const calls = [];
81
- if (deploySalt) {
82
- calls.push(
83
- call(SURFLIQUID_FACTORY_ADDRESS, SURFLIQUID_FACTORY_ABI, "deployVault", [
84
- smartAccount,
85
- deploySalt
86
- ])
87
- );
88
- }
89
- if (permit) {
90
- calls.push(
91
- call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "permit", [
92
- permit.owner,
93
- smartAccount,
94
- permit.value,
95
- permit.deadline,
96
- permit.v,
97
- permit.r,
98
- permit.s
99
- ])
100
- );
101
- }
102
- calls.push(
103
- call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "transferFrom", [owner, smartAccount, amount]),
104
- call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "approve", [vault, amount]),
105
- input.hasInitialDeposit ? call(vault, SURFLIQUID_VAULT_ABI, "userDeposit", [SURFLIQUID_USDC_ADDRESS, amount]) : call(vault, SURFLIQUID_VAULT_ABI, "initialDeposit", [
106
- SURFLIQUID_USDC_ADDRESS,
107
- input.morphoVault,
108
- amount
109
- ])
110
- );
111
- return calls;
112
- }
113
- function buildWithdrawCalls(input) {
114
- return [
115
- call(input.vault, SURFLIQUID_VAULT_ABI, "withdraw", [
116
- SURFLIQUID_USDC_ADDRESS,
117
- input.amount ?? 0n
118
- ])
119
- ];
120
- }
121
- function buildSweepCalls(input) {
122
- return [call(SURFLIQUID_USDC_ADDRESS, USDC_ABI, "transfer", [input.owner, input.amount])];
123
- }
124
-
125
- // src/agents/surfliquid/surfliquid.sponsorship.ts
126
- var SubmittedError = class extends Error {
127
- constructor(message, userOpHash) {
128
- super(message);
129
- this.userOpHash = userOpHash;
130
- this.name = "SubmittedError";
131
- }
132
- userOpHash;
133
- };
134
- var VaultNotSponsorableError = class extends Error {
135
- constructor(message) {
136
- super(message);
137
- this.name = "VaultNotSponsorableError";
138
- }
139
- };
140
- async function resolveVault(ctx) {
141
- const registered = await ctx.api.getVault(ctx.wallet.ownerAddress);
142
- const smartAccount = ctx.wallet.smartAccountAddress;
143
- if (!registered.userVaultAddress) {
144
- const salt2 = registered.deploymentSalt ?? (await ctx.api.prepare(SURFLIQUID_CHAIN_ID)).salt;
145
- return {
146
- vault: await ctx.chain.computeVaultAddress(smartAccount, salt2),
147
- deploySalt: salt2,
148
- registerAfterDeposit: true
149
- };
150
- }
151
- const vault = registered.userVaultAddress;
152
- if (await ctx.chain.isDeployed(vault)) {
153
- const owner = await ctx.chain.readVaultOwner(vault);
154
- if (owner.toLowerCase() !== smartAccount.toLowerCase()) {
155
- throw new VaultNotSponsorableError(`SurfLiquid vault ${vault} is not owned by the smart account`);
156
- }
157
- return { vault, registerAfterDeposit: false };
158
- }
159
- const salt = registered.deploymentSalt;
160
- const deployable = salt ? await ctx.chain.computeVaultAddress(smartAccount, salt) : void 0;
161
- if (!salt || deployable?.toLowerCase() !== vault.toLowerCase()) {
162
- throw new VaultNotSponsorableError(`Registered SurfLiquid vault ${vault} does not match this smart account`);
163
- }
164
- return { vault, deploySalt: salt, registerAfterDeposit: false };
165
- }
166
- async function pickMorphoVault(api) {
167
- const candidates = await api.getBestVault("USDC");
168
- const candidate = candidates.find((option) => option.chainId === SURFLIQUID_CHAIN_ID);
169
- if (!candidate) {
170
- throw new Error(`SurfLiquid has no morpho vault for USDC on chain ${SURFLIQUID_CHAIN_ID}`);
171
- }
172
- return candidate.vaultAddress;
173
- }
174
- async function permitIfShort(input) {
175
- const { chain, wallet, amount } = input;
176
- const allowance = await chain.readAllowance(wallet.ownerAddress, wallet.smartAccountAddress);
177
- if (allowance >= amount) return void 0;
178
- const [{ tokenName, tokenVersion }, nonce] = await Promise.all([
179
- chain.readTokenMeta(),
180
- chain.readPermitNonce(wallet.ownerAddress)
181
- ]);
182
- const message = {
183
- owner: wallet.ownerAddress,
184
- spender: wallet.smartAccountAddress,
185
- value: amount > SURFLIQUID_PERMIT_CAP ? amount : SURFLIQUID_PERMIT_CAP,
186
- nonce,
187
- deadline: BigInt(Math.floor(Date.now() / 1e3)) + SURFLIQUID_PERMIT_TTL_SECONDS
188
- };
189
- const signature = await wallet.signPermit(
190
- buildPermitTypedData({
191
- token: SURFLIQUID_USDC_ADDRESS,
192
- chainId: SURFLIQUID_CHAIN_ID,
193
- tokenName,
194
- tokenVersion,
195
- message
196
- })
197
- );
198
- const { r, s, v, yParity } = parseSignature(signature);
199
- return {
200
- owner: message.owner,
201
- value: message.value,
202
- deadline: message.deadline,
203
- v: Number(v ?? BigInt(yParity + 27)),
204
- r,
205
- s
206
- };
207
- }
208
- async function depositSponsored(input) {
209
- const { api, chain, wallet, amount } = input;
210
- const { vault, deploySalt, registerAfterDeposit } = await resolveVault(input);
211
- const hasInitialDeposit = deploySalt ? false : await chain.hasInitialDeposit(vault, SURFLIQUID_USDC_ADDRESS);
212
- const morphoVault = hasInitialDeposit ? void 0 : await pickMorphoVault(api);
213
- const permit = await permitIfShort({ chain, wallet, amount });
214
- const txHash = await wallet.sendCalls(
215
- buildDepositCalls({
216
- smartAccount: wallet.smartAccountAddress,
217
- owner: wallet.ownerAddress,
218
- vault,
219
- amount,
220
- permit,
221
- hasInitialDeposit,
222
- morphoVault,
223
- deploySalt
224
- })
225
- );
226
- if (registerAfterDeposit && deploySalt) {
227
- try {
228
- await api.confirm({
229
- userVaultAddress: vault,
230
- homeChainId: SURFLIQUID_CHAIN_ID,
231
- deploymentSalt: deploySalt,
232
- initialAssets: []
233
- });
234
- } catch (error) {
235
- console.warn(
236
- "[owney-sdk] SurfLiquid vault registration failed after a successful deposit:",
237
- error instanceof Error ? error.message : String(error)
238
- );
239
- }
240
- }
241
- return { txHash, vault };
242
- }
243
- async function withdrawSponsored(input) {
244
- const { api, chain, wallet, amount } = input;
245
- const registered = await api.getVault(wallet.ownerAddress);
246
- if (!registered.userVaultAddress) {
247
- throw new Error("SurfLiquid has no vault registered for this wallet");
248
- }
249
- const vault = registered.userVaultAddress;
250
- const owner = await chain.readVaultOwner(vault);
251
- if (owner.toLowerCase() !== wallet.smartAccountAddress.toLowerCase()) {
252
- throw new VaultNotSponsorableError(`SurfLiquid vault ${vault} is not owned by the smart account`);
253
- }
254
- const withdrawHash = await wallet.sendCalls(buildWithdrawCalls({ vault, amount }));
255
- try {
256
- const proceeds = await chain.usdcBalanceOf(wallet.smartAccountAddress);
257
- if (proceeds === 0n) return { txHash: withdrawHash, amount: "0" };
258
- const sweepHash = await wallet.sendCalls(
259
- buildSweepCalls({ owner: wallet.ownerAddress, amount: proceeds })
260
- );
261
- return { txHash: sweepHash, amount: proceeds.toString() };
262
- } catch (error) {
263
- throw new SubmittedError(
264
- `SurfLiquid withdrawal ${withdrawHash} landed but the sweep did not: ${error instanceof Error ? error.message : String(error)}`
265
- );
266
- }
267
- }
268
-
269
- export {
270
- SURFLIQUID_CHAIN_ID,
271
- SURFLIQUID_CHAIN_NAME,
272
- SURFLIQUID_USDC_ADDRESS,
273
- SURFLIQUID_SUPPORTED_ASSETS,
274
- SURFLIQUID_ACTION_MAP,
275
- SURFLIQUID_FACTORY_ADDRESS,
276
- SURFLIQUID_FACTORY_ABI,
277
- SURFLIQUID_VAULT_ABI,
278
- USDC_ABI,
279
- SubmittedError,
280
- VaultNotSponsorableError,
281
- depositSponsored,
282
- withdrawSponsored
283
- };
@@ -1,58 +0,0 @@
1
- // src/lib/transfer-auth.ts
2
- import { bytesToHex } from "viem";
3
- var ERC20_META_ABI = [
4
- { type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
5
- { type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
6
- ];
7
- function buildTransferWithAuthorizationTypedData(input) {
8
- return {
9
- domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
10
- types: {
11
- TransferWithAuthorization: [
12
- { name: "from", type: "address" },
13
- { name: "to", type: "address" },
14
- { name: "value", type: "uint256" },
15
- { name: "validAfter", type: "uint256" },
16
- { name: "validBefore", type: "uint256" },
17
- { name: "nonce", type: "bytes32" }
18
- ]
19
- },
20
- primaryType: "TransferWithAuthorization",
21
- message: input.message
22
- };
23
- }
24
- async function readTokenMeta(publicClient, token) {
25
- const [tokenName, tokenVersion] = await Promise.all([
26
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
27
- publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
28
- ]);
29
- return { tokenName, tokenVersion };
30
- }
31
- function randomAuthNonce() {
32
- const bytes = new Uint8Array(32);
33
- globalThis.crypto.getRandomValues(bytes);
34
- return bytesToHex(bytes);
35
- }
36
- function buildPermitTypedData(input) {
37
- return {
38
- domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
39
- types: {
40
- Permit: [
41
- { name: "owner", type: "address" },
42
- { name: "spender", type: "address" },
43
- { name: "value", type: "uint256" },
44
- { name: "nonce", type: "uint256" },
45
- { name: "deadline", type: "uint256" }
46
- ]
47
- },
48
- primaryType: "Permit",
49
- message: input.message
50
- };
51
- }
52
-
53
- export {
54
- buildTransferWithAuthorizationTypedData,
55
- readTokenMeta,
56
- randomAuthNonce,
57
- buildPermitTypedData
58
- };
@@ -1,141 +0,0 @@
1
- // src/errors.ts
2
- var OwneyError = class extends Error {
3
- code;
4
- details;
5
- agentId;
6
- constructor(code, message, details, agentId) {
7
- const prefix = agentId ? `[${code}][agent:${agentId}]` : `[${code}]`;
8
- super(`${prefix} ${message}`);
9
- this.name = "OwneyError";
10
- this.code = code;
11
- this.details = details;
12
- this.agentId = agentId;
13
- }
14
- };
15
- var AgentNotFoundError = class extends OwneyError {
16
- constructor(agentId, available) {
17
- super(
18
- "AGENT_NOT_FOUND",
19
- `Unknown agent "${agentId}". Available agents: ${available.join(", ")}`,
20
- { agentId, available },
21
- agentId
22
- );
23
- this.name = "AgentNotFoundError";
24
- }
25
- };
26
- var NotConnectedError = class extends OwneyError {
27
- constructor() {
28
- super("NOT_CONNECTED", "Not connected. Call sdk.connect(provider) first.");
29
- this.name = "NotConnectedError";
30
- }
31
- };
32
- var AgentChainIncompatibleError = class extends OwneyError {
33
- incompatibleAgents;
34
- connectedChainId;
35
- constructor(incompatibleAgents, connectedChainId) {
36
- const details = incompatibleAgents.map(
37
- ({ agentId, supportedChainIds }) => `"${agentId}" supports chains [${supportedChainIds.join(", ")}]`
38
- ).join("; ");
39
- super(
40
- "AGENT_CHAIN_INCOMPATIBLE",
41
- `Chain ${connectedChainId} is not supported by the following agents: ${details}`,
42
- { incompatibleAgents, connectedChainId }
43
- );
44
- this.name = "AgentChainIncompatibleError";
45
- this.incompatibleAgents = incompatibleAgents;
46
- this.connectedChainId = connectedChainId;
47
- }
48
- };
49
-
50
- // src/lib/debug.ts
51
- var configuredDebug = false;
52
- function setOwneyDebug(enabled) {
53
- configuredDebug = enabled;
54
- }
55
- function isOwneyDebug() {
56
- return globalThis.__OWNEY_DEBUG__ === true || configuredDebug;
57
- }
58
- function debugLog(scope, message, data) {
59
- if (!isOwneyDebug()) return;
60
- if (data === void 0) {
61
- console.log(`[${scope}] ${message}`);
62
- } else {
63
- console.log(`[${scope}] ${message}`, data);
64
- }
65
- }
66
-
67
- // src/lib/routing-api.ts
68
- var ROUTING_API_BASE_URL = "https://owney-routing-api-243946518160.europe-west4.run.app";
69
- async function fetchOrgAgentConfig(apiKey, baseUrl = ROUTING_API_BASE_URL) {
70
- const url = `${baseUrl}/api/v1/agent/org-config`;
71
- try {
72
- const res = await fetch(url, {
73
- method: "GET",
74
- headers: {
75
- "Content-Type": "application/json",
76
- "x-owney-api-key": `${apiKey}`
77
- }
78
- });
79
- if (!res.ok) {
80
- if (res.status !== 404) {
81
- console.warn(
82
- `[owney-sdk] Could not read org agent config (${res.status}); leaving user profiles unchanged.`
83
- );
84
- }
85
- return null;
86
- }
87
- const json = await res.json();
88
- const policy = json.success ? json.data ?? null : null;
89
- debugLog(
90
- "owney-sdk",
91
- policy ? "org agent config: loaded" : "org agent config: none set by this partner \u2014 user profiles will be left as they are",
92
- policy ?? void 0
93
- );
94
- return policy;
95
- } catch (error) {
96
- console.warn(
97
- "[owney-sdk] Could not read org agent config (non-fatal):",
98
- error instanceof Error ? error.message : String(error)
99
- );
100
- return null;
101
- }
102
- }
103
- async function fetchAgentKeys(apiKey, baseUrl = ROUTING_API_BASE_URL) {
104
- const url = `${baseUrl}/api/v1/agent/keys`;
105
- const res = await fetch(url, {
106
- method: "GET",
107
- headers: {
108
- "Content-Type": "application/json",
109
- "x-owney-api-key": `${apiKey}`
110
- }
111
- });
112
- if (!res.ok) {
113
- const text = await res.text().catch(() => "");
114
- throw new OwneyError(
115
- "API_ROUTING_ERROR",
116
- `Routing API error ${res.status}: ${text}`,
117
- { statusCode: res.status, responseBody: text }
118
- );
119
- }
120
- const json = await res.json();
121
- if (!json.success) {
122
- throw new OwneyError(
123
- "API_ROUTING_FAILED",
124
- `Routing API request failed: ${json.message}`,
125
- { message: json.message }
126
- );
127
- }
128
- return json.data;
129
- }
130
-
131
- export {
132
- OwneyError,
133
- AgentNotFoundError,
134
- NotConnectedError,
135
- AgentChainIncompatibleError,
136
- setOwneyDebug,
137
- debugLog,
138
- ROUTING_API_BASE_URL,
139
- fetchOrgAgentConfig,
140
- fetchAgentKeys
141
- };