@owney/sdk 0.4.6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +177 -4
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +179 -2
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -934,6 +934,130 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
934
934
|
return out;
|
|
935
935
|
}
|
|
936
936
|
|
|
937
|
+
// src/client.ts
|
|
938
|
+
var import_viem3 = require("viem");
|
|
939
|
+
var import_chains = require("viem/chains");
|
|
940
|
+
|
|
941
|
+
// src/lib/transfer-auth.ts
|
|
942
|
+
var import_viem2 = require("viem");
|
|
943
|
+
var ERC20_META_ABI = [
|
|
944
|
+
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
|
|
945
|
+
{ type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
|
|
946
|
+
];
|
|
947
|
+
function buildTransferWithAuthorizationTypedData(input) {
|
|
948
|
+
return {
|
|
949
|
+
domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
|
|
950
|
+
types: {
|
|
951
|
+
TransferWithAuthorization: [
|
|
952
|
+
{ name: "from", type: "address" },
|
|
953
|
+
{ name: "to", type: "address" },
|
|
954
|
+
{ name: "value", type: "uint256" },
|
|
955
|
+
{ name: "validAfter", type: "uint256" },
|
|
956
|
+
{ name: "validBefore", type: "uint256" },
|
|
957
|
+
{ name: "nonce", type: "bytes32" }
|
|
958
|
+
]
|
|
959
|
+
},
|
|
960
|
+
primaryType: "TransferWithAuthorization",
|
|
961
|
+
message: input.message
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
async function readTokenMeta(publicClient, token) {
|
|
965
|
+
const [tokenName, tokenVersion] = await Promise.all([
|
|
966
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
|
|
967
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
|
|
968
|
+
]);
|
|
969
|
+
return { tokenName, tokenVersion };
|
|
970
|
+
}
|
|
971
|
+
function randomAuthNonce() {
|
|
972
|
+
const bytes = new Uint8Array(32);
|
|
973
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
974
|
+
return (0, import_viem2.bytesToHex)(bytes);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/lib/sponsor-client.ts
|
|
978
|
+
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
979
|
+
async function postSponsorTransferAuth(input) {
|
|
980
|
+
const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
981
|
+
let res;
|
|
982
|
+
try {
|
|
983
|
+
res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
984
|
+
method: "POST",
|
|
985
|
+
headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
|
|
986
|
+
body: JSON.stringify(input.body)
|
|
987
|
+
});
|
|
988
|
+
} catch (networkError) {
|
|
989
|
+
throw new OwneyError(
|
|
990
|
+
"SPONSOR_REQUEST_FAILED",
|
|
991
|
+
`Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
|
|
992
|
+
{ cause: String(networkError) }
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
const text = await res.text();
|
|
996
|
+
let parsed = null;
|
|
997
|
+
try {
|
|
998
|
+
parsed = JSON.parse(text);
|
|
999
|
+
} catch {
|
|
1000
|
+
}
|
|
1001
|
+
if (!res.ok || !parsed?.success || !parsed.data) {
|
|
1002
|
+
throw new OwneyError(
|
|
1003
|
+
"SPONSOR_REQUEST_FAILED",
|
|
1004
|
+
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
1005
|
+
{ statusCode: res.status, responseBody: text.slice(0, 500) }
|
|
1006
|
+
);
|
|
1007
|
+
}
|
|
1008
|
+
return parsed.data;
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// src/lib/sponsored-deposit.ts
|
|
1012
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1013
|
+
function makeSponsoredDepositCallback(deps) {
|
|
1014
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1015
|
+
return async (smartWallet, chainId, amount) => {
|
|
1016
|
+
const cid = chainId;
|
|
1017
|
+
const token = deps.tokenAddressByChain[cid];
|
|
1018
|
+
if (!token) {
|
|
1019
|
+
throw new OwneyError(
|
|
1020
|
+
"CHAIN_UNSUPPORTED",
|
|
1021
|
+
`No sponsored token configured for chain ${chainId}`
|
|
1022
|
+
);
|
|
1023
|
+
}
|
|
1024
|
+
const pub = deps.getPublicClient(cid);
|
|
1025
|
+
const wallet = deps.getWalletClient(cid);
|
|
1026
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1027
|
+
const validAfter = 0n;
|
|
1028
|
+
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1029
|
+
const nonce = randomAuthNonce();
|
|
1030
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1031
|
+
token,
|
|
1032
|
+
chainId: cid,
|
|
1033
|
+
tokenName,
|
|
1034
|
+
tokenVersion,
|
|
1035
|
+
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1036
|
+
});
|
|
1037
|
+
const authSignature = await wallet.signTypedData(
|
|
1038
|
+
{ account: deps.ownerAddress, ...typedData }
|
|
1039
|
+
);
|
|
1040
|
+
const result = await post({
|
|
1041
|
+
baseUrl: deps.baseUrl,
|
|
1042
|
+
apiKey: deps.apiKey,
|
|
1043
|
+
body: {
|
|
1044
|
+
chainId: cid,
|
|
1045
|
+
token,
|
|
1046
|
+
from: deps.ownerAddress,
|
|
1047
|
+
to: smartWallet,
|
|
1048
|
+
value: amount,
|
|
1049
|
+
validAfter: validAfter.toString(),
|
|
1050
|
+
validBefore: validBefore.toString(),
|
|
1051
|
+
nonce,
|
|
1052
|
+
authSignature,
|
|
1053
|
+
tokenName,
|
|
1054
|
+
tokenVersion
|
|
1055
|
+
}
|
|
1056
|
+
});
|
|
1057
|
+
return result.txHash;
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
937
1061
|
// src/client.ts
|
|
938
1062
|
function encodeMultiAgentCursor(map) {
|
|
939
1063
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -955,6 +1079,11 @@ function decodeMultiAgentCursor(token) {
|
|
|
955
1079
|
}
|
|
956
1080
|
return parsed;
|
|
957
1081
|
}
|
|
1082
|
+
var SPONSORED_USDC_BY_CHAIN = {
|
|
1083
|
+
8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1084
|
+
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
|
|
1085
|
+
};
|
|
1086
|
+
var VIEM_CHAIN = { 8453: import_chains.base, 42161: import_chains.arbitrum };
|
|
958
1087
|
var OwneySDK = class {
|
|
959
1088
|
agents = /* @__PURE__ */ new Map();
|
|
960
1089
|
activeAgents = /* @__PURE__ */ new Set();
|
|
@@ -967,6 +1096,7 @@ var OwneySDK = class {
|
|
|
967
1096
|
state = null;
|
|
968
1097
|
apiKey;
|
|
969
1098
|
zyfaiRpcUrls;
|
|
1099
|
+
cachedSponsoredCallback = null;
|
|
970
1100
|
initializingAgentsPromise = null;
|
|
971
1101
|
constructor(config) {
|
|
972
1102
|
this.apiKey = config.apiKey;
|
|
@@ -990,6 +1120,7 @@ var OwneySDK = class {
|
|
|
990
1120
|
);
|
|
991
1121
|
}
|
|
992
1122
|
this.state = { provider, walletAddress, chainId: null };
|
|
1123
|
+
this.cachedSponsoredCallback = null;
|
|
993
1124
|
}
|
|
994
1125
|
/**
|
|
995
1126
|
* Disconnect from all agents and clear connection state.
|
|
@@ -1002,6 +1133,7 @@ var OwneySDK = class {
|
|
|
1002
1133
|
this.activeAgents.clear();
|
|
1003
1134
|
this.disabledAgents.clear();
|
|
1004
1135
|
this.state = null;
|
|
1136
|
+
this.cachedSponsoredCallback = null;
|
|
1005
1137
|
}
|
|
1006
1138
|
isAgentDisabled(agentId) {
|
|
1007
1139
|
return this.disabledAgents.has(agentId);
|
|
@@ -1035,6 +1167,46 @@ var OwneySDK = class {
|
|
|
1035
1167
|
}
|
|
1036
1168
|
return chainId;
|
|
1037
1169
|
}
|
|
1170
|
+
requireConnectedProvider() {
|
|
1171
|
+
if (!this.state?.provider) {
|
|
1172
|
+
throw new OwneyError(
|
|
1173
|
+
"NOT_CONNECTED",
|
|
1174
|
+
"connect(provider) must be called before deposit",
|
|
1175
|
+
{}
|
|
1176
|
+
);
|
|
1177
|
+
}
|
|
1178
|
+
return this.state.provider;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
1182
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
1183
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1184
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1185
|
+
*/
|
|
1186
|
+
getDefaultSponsoredCallback() {
|
|
1187
|
+
if (this.cachedSponsoredCallback)
|
|
1188
|
+
return this.cachedSponsoredCallback;
|
|
1189
|
+
const provider = this.requireConnectedProvider();
|
|
1190
|
+
const owner = this.state.walletAddress;
|
|
1191
|
+
this.cachedSponsoredCallback = makeSponsoredDepositCallback({
|
|
1192
|
+
apiKey: this.apiKey,
|
|
1193
|
+
ownerAddress: owner,
|
|
1194
|
+
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1195
|
+
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1196
|
+
// PublicClient/WalletClient param types — structurally identical at
|
|
1197
|
+
// runtime, but the two share a name TS treats as unrelated.
|
|
1198
|
+
getPublicClient: (cid) => (0, import_viem3.createPublicClient)({
|
|
1199
|
+
chain: VIEM_CHAIN[cid],
|
|
1200
|
+
transport: (0, import_viem3.custom)(provider)
|
|
1201
|
+
}),
|
|
1202
|
+
getWalletClient: (cid) => (0, import_viem3.createWalletClient)({
|
|
1203
|
+
account: owner,
|
|
1204
|
+
chain: VIEM_CHAIN[cid],
|
|
1205
|
+
transport: (0, import_viem3.custom)(provider)
|
|
1206
|
+
})
|
|
1207
|
+
});
|
|
1208
|
+
return this.cachedSponsoredCallback;
|
|
1209
|
+
}
|
|
1038
1210
|
getAgent(agentId) {
|
|
1039
1211
|
const agent = this.agents.get(agentId);
|
|
1040
1212
|
if (!agent) {
|
|
@@ -1188,6 +1360,7 @@ var OwneySDK = class {
|
|
|
1188
1360
|
}
|
|
1189
1361
|
const state = this.requireState();
|
|
1190
1362
|
const chainId = this.requireChainId();
|
|
1363
|
+
const effectiveCallback = depositCallback ?? this.getDefaultSponsoredCallback();
|
|
1191
1364
|
if (agentId) {
|
|
1192
1365
|
if (this.isAgentDisabled(agentId)) {
|
|
1193
1366
|
throw new OwneyError(
|
|
@@ -1202,7 +1375,7 @@ var OwneySDK = class {
|
|
|
1202
1375
|
return withFailureReporting(
|
|
1203
1376
|
this.apiKey,
|
|
1204
1377
|
agent.id,
|
|
1205
|
-
() => agent.deposit(state, chainId, amount,
|
|
1378
|
+
() => agent.deposit(state, chainId, amount, effectiveCallback)
|
|
1206
1379
|
);
|
|
1207
1380
|
}
|
|
1208
1381
|
const totalAmount = BigInt(amount);
|
|
@@ -1236,7 +1409,7 @@ var OwneySDK = class {
|
|
|
1236
1409
|
agentResults[agent.id] = await withFailureReporting(
|
|
1237
1410
|
this.apiKey,
|
|
1238
1411
|
agent.id,
|
|
1239
|
-
() => agent.deposit(state, chainId, agentAmount,
|
|
1412
|
+
() => agent.deposit(state, chainId, agentAmount, effectiveCallback)
|
|
1240
1413
|
);
|
|
1241
1414
|
}
|
|
1242
1415
|
return { agentResults };
|
|
@@ -1854,7 +2027,7 @@ var OwneySDK = class {
|
|
|
1854
2027
|
};
|
|
1855
2028
|
|
|
1856
2029
|
// src/agents/zyfai/zyfai.siwx.ts
|
|
1857
|
-
var
|
|
2030
|
+
var import_viem4 = require("viem");
|
|
1858
2031
|
var import_siwe = require("siwe");
|
|
1859
2032
|
var import_sdk2 = require("@zyfai/sdk");
|
|
1860
2033
|
|
|
@@ -1936,7 +2109,7 @@ function buildSIWXConfig(deps) {
|
|
|
1936
2109
|
issuedAt,
|
|
1937
2110
|
toString() {
|
|
1938
2111
|
return new import_siwe.SiweMessage({
|
|
1939
|
-
address: (0,
|
|
2112
|
+
address: (0, import_viem4.getAddress)(accountAddress),
|
|
1940
2113
|
chainId: numericChainId(chainId),
|
|
1941
2114
|
domain,
|
|
1942
2115
|
uri,
|
package/dist/index.d.cts
CHANGED
|
@@ -101,7 +101,7 @@ type AgentsApyOptions = {
|
|
|
101
101
|
type DepositOptions = {
|
|
102
102
|
amount: string;
|
|
103
103
|
asset: Asset;
|
|
104
|
-
depositCallback
|
|
104
|
+
depositCallback?: DepositCallback;
|
|
105
105
|
agentId?: AgentId;
|
|
106
106
|
};
|
|
107
107
|
|
|
@@ -237,6 +237,7 @@ declare class OwneySDK {
|
|
|
237
237
|
private state;
|
|
238
238
|
private apiKey;
|
|
239
239
|
private zyfaiRpcUrls?;
|
|
240
|
+
private cachedSponsoredCallback;
|
|
240
241
|
private initializingAgentsPromise;
|
|
241
242
|
constructor(config: OwneySDKConfig);
|
|
242
243
|
/**
|
|
@@ -263,6 +264,14 @@ declare class OwneySDK {
|
|
|
263
264
|
getActiveChainId(): number | null;
|
|
264
265
|
private requireState;
|
|
265
266
|
private requireChainId;
|
|
267
|
+
private requireConnectedProvider;
|
|
268
|
+
/**
|
|
269
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
270
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
271
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
272
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
273
|
+
*/
|
|
274
|
+
private getDefaultSponsoredCallback;
|
|
266
275
|
private getAgent;
|
|
267
276
|
private getActiveAgents;
|
|
268
277
|
private ensureAgentsInitialized;
|
|
@@ -390,7 +399,7 @@ declare class OwneySDK {
|
|
|
390
399
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
391
400
|
}
|
|
392
401
|
|
|
393
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
402
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
394
403
|
declare class OwneyError extends Error {
|
|
395
404
|
readonly code: OwneyErrorCode;
|
|
396
405
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -101,7 +101,7 @@ type AgentsApyOptions = {
|
|
|
101
101
|
type DepositOptions = {
|
|
102
102
|
amount: string;
|
|
103
103
|
asset: Asset;
|
|
104
|
-
depositCallback
|
|
104
|
+
depositCallback?: DepositCallback;
|
|
105
105
|
agentId?: AgentId;
|
|
106
106
|
};
|
|
107
107
|
|
|
@@ -237,6 +237,7 @@ declare class OwneySDK {
|
|
|
237
237
|
private state;
|
|
238
238
|
private apiKey;
|
|
239
239
|
private zyfaiRpcUrls?;
|
|
240
|
+
private cachedSponsoredCallback;
|
|
240
241
|
private initializingAgentsPromise;
|
|
241
242
|
constructor(config: OwneySDKConfig);
|
|
242
243
|
/**
|
|
@@ -263,6 +264,14 @@ declare class OwneySDK {
|
|
|
263
264
|
getActiveChainId(): number | null;
|
|
264
265
|
private requireState;
|
|
265
266
|
private requireChainId;
|
|
267
|
+
private requireConnectedProvider;
|
|
268
|
+
/**
|
|
269
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
270
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
271
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
272
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
273
|
+
*/
|
|
274
|
+
private getDefaultSponsoredCallback;
|
|
266
275
|
private getAgent;
|
|
267
276
|
private getActiveAgents;
|
|
268
277
|
private ensureAgentsInitialized;
|
|
@@ -390,7 +399,7 @@ declare class OwneySDK {
|
|
|
390
399
|
getAgentAllocation(): Promise<OwneyAgentAllocation>;
|
|
391
400
|
}
|
|
392
401
|
|
|
393
|
-
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
402
|
+
type OwneyErrorCode = "NOT_CONNECTED" | "NO_ACTIVE_CHAIN" | "WALLET_NO_ACCOUNTS" | "WALLET_ADDRESS_REQUIRED" | "AGENT_NOT_FOUND" | "AGENT_CHAIN_INCOMPATIBLE" | "AGENT_EMPTY_LIST" | "AGENT_DISABLED" | "CHAIN_UNSUPPORTED" | "CHAIN_NO_COMPATIBLE_AGENTS" | "ASSET_UNSUPPORTED" | "ASSET_NO_COMPATIBLE_AGENTS" | "DEPOSIT_AMOUNT_BELOW_MINIMUM" | "DEPOSIT_CALLBACK_REQUIRED" | "DEPOSIT_CALLBACK_INVALID" | "DEPOSIT_NO_PERMITTED_TOKENS" | "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" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
394
403
|
declare class OwneyError extends Error {
|
|
395
404
|
readonly code: OwneyErrorCode;
|
|
396
405
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -902,6 +902,134 @@ function aggregateApyByChainAndAsset(agentApys, agentBalances) {
|
|
|
902
902
|
return out;
|
|
903
903
|
}
|
|
904
904
|
|
|
905
|
+
// src/client.ts
|
|
906
|
+
import {
|
|
907
|
+
createPublicClient,
|
|
908
|
+
createWalletClient,
|
|
909
|
+
custom
|
|
910
|
+
} from "viem";
|
|
911
|
+
import { base, arbitrum } from "viem/chains";
|
|
912
|
+
|
|
913
|
+
// src/lib/transfer-auth.ts
|
|
914
|
+
import { bytesToHex } from "viem";
|
|
915
|
+
var ERC20_META_ABI = [
|
|
916
|
+
{ type: "function", name: "name", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] },
|
|
917
|
+
{ type: "function", name: "version", stateMutability: "view", inputs: [], outputs: [{ name: "", type: "string" }] }
|
|
918
|
+
];
|
|
919
|
+
function buildTransferWithAuthorizationTypedData(input) {
|
|
920
|
+
return {
|
|
921
|
+
domain: { name: input.tokenName, version: input.tokenVersion, chainId: input.chainId, verifyingContract: input.token },
|
|
922
|
+
types: {
|
|
923
|
+
TransferWithAuthorization: [
|
|
924
|
+
{ name: "from", type: "address" },
|
|
925
|
+
{ name: "to", type: "address" },
|
|
926
|
+
{ name: "value", type: "uint256" },
|
|
927
|
+
{ name: "validAfter", type: "uint256" },
|
|
928
|
+
{ name: "validBefore", type: "uint256" },
|
|
929
|
+
{ name: "nonce", type: "bytes32" }
|
|
930
|
+
]
|
|
931
|
+
},
|
|
932
|
+
primaryType: "TransferWithAuthorization",
|
|
933
|
+
message: input.message
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
async function readTokenMeta(publicClient, token) {
|
|
937
|
+
const [tokenName, tokenVersion] = await Promise.all([
|
|
938
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "name" }),
|
|
939
|
+
publicClient.readContract({ address: token, abi: ERC20_META_ABI, functionName: "version" }).catch(() => "2")
|
|
940
|
+
]);
|
|
941
|
+
return { tokenName, tokenVersion };
|
|
942
|
+
}
|
|
943
|
+
function randomAuthNonce() {
|
|
944
|
+
const bytes = new Uint8Array(32);
|
|
945
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
946
|
+
return bytesToHex(bytes);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// src/lib/sponsor-client.ts
|
|
950
|
+
var ROUTING_API_BASE_URL3 = "https://owney-routing-api-243946518160.europe-west4.run.app";
|
|
951
|
+
async function postSponsorTransferAuth(input) {
|
|
952
|
+
const base2 = input.baseUrl ?? ROUTING_API_BASE_URL3;
|
|
953
|
+
let res;
|
|
954
|
+
try {
|
|
955
|
+
res = await fetch(`${base2}/api/v1/sponsor/erc20-transfer-auth`, {
|
|
956
|
+
method: "POST",
|
|
957
|
+
headers: { "content-type": "application/json", "x-owney-api-key": input.apiKey },
|
|
958
|
+
body: JSON.stringify(input.body)
|
|
959
|
+
});
|
|
960
|
+
} catch (networkError) {
|
|
961
|
+
throw new OwneyError(
|
|
962
|
+
"SPONSOR_REQUEST_FAILED",
|
|
963
|
+
`Sponsor API network error: ${networkError instanceof Error ? networkError.message : String(networkError)}`,
|
|
964
|
+
{ cause: String(networkError) }
|
|
965
|
+
);
|
|
966
|
+
}
|
|
967
|
+
const text = await res.text();
|
|
968
|
+
let parsed = null;
|
|
969
|
+
try {
|
|
970
|
+
parsed = JSON.parse(text);
|
|
971
|
+
} catch {
|
|
972
|
+
}
|
|
973
|
+
if (!res.ok || !parsed?.success || !parsed.data) {
|
|
974
|
+
throw new OwneyError(
|
|
975
|
+
"SPONSOR_REQUEST_FAILED",
|
|
976
|
+
`Sponsor API error ${res.status}: ${parsed?.message ?? text.slice(0, 500)}`,
|
|
977
|
+
{ statusCode: res.status, responseBody: text.slice(0, 500) }
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
return parsed.data;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// src/lib/sponsored-deposit.ts
|
|
984
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
985
|
+
function makeSponsoredDepositCallback(deps) {
|
|
986
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
987
|
+
return async (smartWallet, chainId, amount) => {
|
|
988
|
+
const cid = chainId;
|
|
989
|
+
const token = deps.tokenAddressByChain[cid];
|
|
990
|
+
if (!token) {
|
|
991
|
+
throw new OwneyError(
|
|
992
|
+
"CHAIN_UNSUPPORTED",
|
|
993
|
+
`No sponsored token configured for chain ${chainId}`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
const pub = deps.getPublicClient(cid);
|
|
997
|
+
const wallet = deps.getWalletClient(cid);
|
|
998
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
999
|
+
const validAfter = 0n;
|
|
1000
|
+
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1001
|
+
const nonce = randomAuthNonce();
|
|
1002
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1003
|
+
token,
|
|
1004
|
+
chainId: cid,
|
|
1005
|
+
tokenName,
|
|
1006
|
+
tokenVersion,
|
|
1007
|
+
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1008
|
+
});
|
|
1009
|
+
const authSignature = await wallet.signTypedData(
|
|
1010
|
+
{ account: deps.ownerAddress, ...typedData }
|
|
1011
|
+
);
|
|
1012
|
+
const result = await post({
|
|
1013
|
+
baseUrl: deps.baseUrl,
|
|
1014
|
+
apiKey: deps.apiKey,
|
|
1015
|
+
body: {
|
|
1016
|
+
chainId: cid,
|
|
1017
|
+
token,
|
|
1018
|
+
from: deps.ownerAddress,
|
|
1019
|
+
to: smartWallet,
|
|
1020
|
+
value: amount,
|
|
1021
|
+
validAfter: validAfter.toString(),
|
|
1022
|
+
validBefore: validBefore.toString(),
|
|
1023
|
+
nonce,
|
|
1024
|
+
authSignature,
|
|
1025
|
+
tokenName,
|
|
1026
|
+
tokenVersion
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
return result.txHash;
|
|
1030
|
+
};
|
|
1031
|
+
}
|
|
1032
|
+
|
|
905
1033
|
// src/client.ts
|
|
906
1034
|
function encodeMultiAgentCursor(map) {
|
|
907
1035
|
return Buffer.from(JSON.stringify(map), "utf8").toString("base64");
|
|
@@ -923,6 +1051,11 @@ function decodeMultiAgentCursor(token) {
|
|
|
923
1051
|
}
|
|
924
1052
|
return parsed;
|
|
925
1053
|
}
|
|
1054
|
+
var SPONSORED_USDC_BY_CHAIN = {
|
|
1055
|
+
8453: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1056
|
+
42161: "0xaf88d065e77c8cc2239327c5edb3a432268e5831"
|
|
1057
|
+
};
|
|
1058
|
+
var VIEM_CHAIN = { 8453: base, 42161: arbitrum };
|
|
926
1059
|
var OwneySDK = class {
|
|
927
1060
|
agents = /* @__PURE__ */ new Map();
|
|
928
1061
|
activeAgents = /* @__PURE__ */ new Set();
|
|
@@ -935,6 +1068,7 @@ var OwneySDK = class {
|
|
|
935
1068
|
state = null;
|
|
936
1069
|
apiKey;
|
|
937
1070
|
zyfaiRpcUrls;
|
|
1071
|
+
cachedSponsoredCallback = null;
|
|
938
1072
|
initializingAgentsPromise = null;
|
|
939
1073
|
constructor(config) {
|
|
940
1074
|
this.apiKey = config.apiKey;
|
|
@@ -958,6 +1092,7 @@ var OwneySDK = class {
|
|
|
958
1092
|
);
|
|
959
1093
|
}
|
|
960
1094
|
this.state = { provider, walletAddress, chainId: null };
|
|
1095
|
+
this.cachedSponsoredCallback = null;
|
|
961
1096
|
}
|
|
962
1097
|
/**
|
|
963
1098
|
* Disconnect from all agents and clear connection state.
|
|
@@ -970,6 +1105,7 @@ var OwneySDK = class {
|
|
|
970
1105
|
this.activeAgents.clear();
|
|
971
1106
|
this.disabledAgents.clear();
|
|
972
1107
|
this.state = null;
|
|
1108
|
+
this.cachedSponsoredCallback = null;
|
|
973
1109
|
}
|
|
974
1110
|
isAgentDisabled(agentId) {
|
|
975
1111
|
return this.disabledAgents.has(agentId);
|
|
@@ -1003,6 +1139,46 @@ var OwneySDK = class {
|
|
|
1003
1139
|
}
|
|
1004
1140
|
return chainId;
|
|
1005
1141
|
}
|
|
1142
|
+
requireConnectedProvider() {
|
|
1143
|
+
if (!this.state?.provider) {
|
|
1144
|
+
throw new OwneyError(
|
|
1145
|
+
"NOT_CONNECTED",
|
|
1146
|
+
"connect(provider) must be called before deposit",
|
|
1147
|
+
{}
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
return this.state.provider;
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* Lazily builds (and caches) the default EIP-3009 sponsored deposit callback
|
|
1154
|
+
* used when the caller omits `depositCallback`. Wraps the connected EIP-1193
|
|
1155
|
+
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1156
|
+
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1157
|
+
*/
|
|
1158
|
+
getDefaultSponsoredCallback() {
|
|
1159
|
+
if (this.cachedSponsoredCallback)
|
|
1160
|
+
return this.cachedSponsoredCallback;
|
|
1161
|
+
const provider = this.requireConnectedProvider();
|
|
1162
|
+
const owner = this.state.walletAddress;
|
|
1163
|
+
this.cachedSponsoredCallback = makeSponsoredDepositCallback({
|
|
1164
|
+
apiKey: this.apiKey,
|
|
1165
|
+
ownerAddress: owner,
|
|
1166
|
+
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1167
|
+
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1168
|
+
// PublicClient/WalletClient param types — structurally identical at
|
|
1169
|
+
// runtime, but the two share a name TS treats as unrelated.
|
|
1170
|
+
getPublicClient: (cid) => createPublicClient({
|
|
1171
|
+
chain: VIEM_CHAIN[cid],
|
|
1172
|
+
transport: custom(provider)
|
|
1173
|
+
}),
|
|
1174
|
+
getWalletClient: (cid) => createWalletClient({
|
|
1175
|
+
account: owner,
|
|
1176
|
+
chain: VIEM_CHAIN[cid],
|
|
1177
|
+
transport: custom(provider)
|
|
1178
|
+
})
|
|
1179
|
+
});
|
|
1180
|
+
return this.cachedSponsoredCallback;
|
|
1181
|
+
}
|
|
1006
1182
|
getAgent(agentId) {
|
|
1007
1183
|
const agent = this.agents.get(agentId);
|
|
1008
1184
|
if (!agent) {
|
|
@@ -1156,6 +1332,7 @@ var OwneySDK = class {
|
|
|
1156
1332
|
}
|
|
1157
1333
|
const state = this.requireState();
|
|
1158
1334
|
const chainId = this.requireChainId();
|
|
1335
|
+
const effectiveCallback = depositCallback ?? this.getDefaultSponsoredCallback();
|
|
1159
1336
|
if (agentId) {
|
|
1160
1337
|
if (this.isAgentDisabled(agentId)) {
|
|
1161
1338
|
throw new OwneyError(
|
|
@@ -1170,7 +1347,7 @@ var OwneySDK = class {
|
|
|
1170
1347
|
return withFailureReporting(
|
|
1171
1348
|
this.apiKey,
|
|
1172
1349
|
agent.id,
|
|
1173
|
-
() => agent.deposit(state, chainId, amount,
|
|
1350
|
+
() => agent.deposit(state, chainId, amount, effectiveCallback)
|
|
1174
1351
|
);
|
|
1175
1352
|
}
|
|
1176
1353
|
const totalAmount = BigInt(amount);
|
|
@@ -1204,7 +1381,7 @@ var OwneySDK = class {
|
|
|
1204
1381
|
agentResults[agent.id] = await withFailureReporting(
|
|
1205
1382
|
this.apiKey,
|
|
1206
1383
|
agent.id,
|
|
1207
|
-
() => agent.deposit(state, chainId, agentAmount,
|
|
1384
|
+
() => agent.deposit(state, chainId, agentAmount, effectiveCallback)
|
|
1208
1385
|
);
|
|
1209
1386
|
}
|
|
1210
1387
|
return { agentResults };
|