@owney/sdk 0.7.3 → 0.7.5
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 +128 -8
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +128 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1318,20 +1318,94 @@ var ZyfaiAgent = class {
|
|
|
1318
1318
|
);
|
|
1319
1319
|
}
|
|
1320
1320
|
}
|
|
1321
|
+
/**
|
|
1322
|
+
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
1323
|
+
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
1324
|
+
* was onboarded to. Legacy wallets (created before @zyfai/sdk 0.2.44) have no
|
|
1325
|
+
* pool record.
|
|
1326
|
+
*
|
|
1327
|
+
* A failed lookup returns false rather than throwing: misclassifying is
|
|
1328
|
+
* recoverable (ensureWalletDeployed tries the other deploy call), but
|
|
1329
|
+
* failing the deposit outright is not.
|
|
1330
|
+
*/
|
|
1331
|
+
async isPredeployedPoolWallet(ownerAddress, smartWallet) {
|
|
1332
|
+
try {
|
|
1333
|
+
const byEoa = await this.sdk.getSmartWalletByEOA(ownerAddress);
|
|
1334
|
+
return typeof byEoa?.smartWallet === "string" && byEoa.smartWallet.toLowerCase() === smartWallet.toLowerCase();
|
|
1335
|
+
} catch (error) {
|
|
1336
|
+
console.warn(
|
|
1337
|
+
"[zyfai] getSmartWalletByEOA failed; assuming a legacy wallet:",
|
|
1338
|
+
error instanceof Error ? error.message : String(error)
|
|
1339
|
+
);
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
/**
|
|
1344
|
+
* Guarantee the user's Safe has code on `chainId` before anything transfers
|
|
1345
|
+
* funds into it, and return its address.
|
|
1346
|
+
*
|
|
1347
|
+
* Zyfai predeploys wallets created since @zyfai/sdk 0.2.44, but ONLY on the
|
|
1348
|
+
* chains they were onboarded to. Legacy wallets, and any chain a pool wallet
|
|
1349
|
+
* has not been onboarded to, are *counterfactual*: `getSmartWalletAddress`
|
|
1350
|
+
* returns a real deterministic address that holds no code yet. Depositing
|
|
1351
|
+
* there strands the funds until the Safe is deployed, and Owney's own sponsor
|
|
1352
|
+
* relayer refuses to broadcast to an address with no bytecode
|
|
1353
|
+
* (`to-address.guard-helper.ts`), so the deposit fails as an opaque 500.
|
|
1354
|
+
*
|
|
1355
|
+
* ROUT-320 removed the old deploySafe step believing every wallet was
|
|
1356
|
+
* predeployed from 0.2.44 on. Zyf later clarified that only NEW wallets are;
|
|
1357
|
+
* old ones still need the legacy flow. Hence the gate is on the per-chain
|
|
1358
|
+
* `isDeployed` flag rather than on the wallet's age — that covers both a
|
|
1359
|
+
* legacy wallet and a pool wallet on a fresh chain.
|
|
1360
|
+
*/
|
|
1361
|
+
async ensureWalletDeployed(ownerAddress, chainId) {
|
|
1362
|
+
const wallet = await this.sdk.getSmartWalletAddress(ownerAddress, chainId);
|
|
1363
|
+
if (wallet.isDeployed) return wallet.address;
|
|
1364
|
+
const poolFirst = await this.isPredeployedPoolWallet(
|
|
1365
|
+
ownerAddress,
|
|
1366
|
+
wallet.address
|
|
1367
|
+
);
|
|
1368
|
+
const deployAsPool = () => this.sdk.deployOnChains([chainId]);
|
|
1369
|
+
const deployAsLegacy = () => (
|
|
1370
|
+
// `createSessionKey: false` — session keys are backend-owned since the
|
|
1371
|
+
// predeployed-pool rollout; asking for one here costs a signature prompt
|
|
1372
|
+
// and is rejected anyway.
|
|
1373
|
+
this.sdk.deploySafe(ownerAddress, chainId, "aggressive", false)
|
|
1374
|
+
);
|
|
1375
|
+
const [first, second] = poolFirst ? [deployAsPool, deployAsLegacy] : [deployAsLegacy, deployAsPool];
|
|
1376
|
+
try {
|
|
1377
|
+
await first();
|
|
1378
|
+
} catch (error) {
|
|
1379
|
+
console.warn(
|
|
1380
|
+
`[zyfai] ${poolFirst ? "deployOnChains" : "deploySafe"} failed on chain ${chainId}; trying the other deploy path:`,
|
|
1381
|
+
error instanceof Error ? error.message : String(error)
|
|
1382
|
+
);
|
|
1383
|
+
await second();
|
|
1384
|
+
}
|
|
1385
|
+
const redeployed = await this.sdk.getSmartWalletAddress(
|
|
1386
|
+
ownerAddress,
|
|
1387
|
+
chainId
|
|
1388
|
+
);
|
|
1389
|
+
if (!redeployed.isDeployed) {
|
|
1390
|
+
throw new OwneyError(
|
|
1391
|
+
"WALLET_NOT_DEPLOYED",
|
|
1392
|
+
`Smart wallet ${redeployed.address} is still not deployed on chain ${chainId}. Depositing would send funds to an address with no code.`,
|
|
1393
|
+
{ chainId, smartWallet: redeployed.address },
|
|
1394
|
+
this.id
|
|
1395
|
+
);
|
|
1396
|
+
}
|
|
1397
|
+
return redeployed.address;
|
|
1398
|
+
}
|
|
1321
1399
|
async deposit(state, chainId, amount, asset, depositCallback) {
|
|
1322
1400
|
try {
|
|
1323
1401
|
const validChainId = isValidChainId(chainId);
|
|
1324
1402
|
await this.ensureConnected(state, validChainId);
|
|
1325
1403
|
if (depositCallback) {
|
|
1326
|
-
const
|
|
1404
|
+
const smartWallet = await this.ensureWalletDeployed(
|
|
1327
1405
|
this.getAddress(),
|
|
1328
1406
|
validChainId
|
|
1329
1407
|
);
|
|
1330
|
-
const txHash = await depositCallback(
|
|
1331
|
-
wallet.address,
|
|
1332
|
-
validChainId,
|
|
1333
|
-
amount
|
|
1334
|
-
);
|
|
1408
|
+
const txHash = await depositCallback(smartWallet, validChainId, amount);
|
|
1335
1409
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
1336
1410
|
try {
|
|
1337
1411
|
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
@@ -1341,8 +1415,9 @@ var ZyfaiAgent = class {
|
|
|
1341
1415
|
logError
|
|
1342
1416
|
);
|
|
1343
1417
|
}
|
|
1344
|
-
return { txHash, smartWallet
|
|
1418
|
+
return { txHash, smartWallet, amount };
|
|
1345
1419
|
}
|
|
1420
|
+
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
1346
1421
|
const raw = await this.sdk.depositFunds(
|
|
1347
1422
|
this.getAddress(),
|
|
1348
1423
|
validChainId,
|
|
@@ -1926,6 +2001,41 @@ async function readErc20Balance(publicClient, token, owner) {
|
|
|
1926
2001
|
});
|
|
1927
2002
|
}
|
|
1928
2003
|
|
|
2004
|
+
// src/lib/chain-guard.ts
|
|
2005
|
+
var CHAIN_NAMES = {
|
|
2006
|
+
1: "Ethereum",
|
|
2007
|
+
8453: "Base",
|
|
2008
|
+
42161: "Arbitrum"
|
|
2009
|
+
};
|
|
2010
|
+
function chainName(chainId) {
|
|
2011
|
+
return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
|
|
2012
|
+
}
|
|
2013
|
+
async function ensureWalletOnChain(pub, wallet, expected) {
|
|
2014
|
+
const actual = await pub.getChainId();
|
|
2015
|
+
if (actual === expected) return;
|
|
2016
|
+
try {
|
|
2017
|
+
await wallet.switchChain({ id: expected });
|
|
2018
|
+
} catch (error) {
|
|
2019
|
+
throw new OwneyError(
|
|
2020
|
+
"CHAIN_MISMATCH",
|
|
2021
|
+
`Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
|
|
2022
|
+
{
|
|
2023
|
+
expectedChainId: expected,
|
|
2024
|
+
actualChainId: actual,
|
|
2025
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
2026
|
+
}
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
2029
|
+
const after = await pub.getChainId();
|
|
2030
|
+
if (after !== expected) {
|
|
2031
|
+
throw new OwneyError(
|
|
2032
|
+
"CHAIN_MISMATCH",
|
|
2033
|
+
`Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
|
|
2034
|
+
{ expectedChainId: expected, actualChainId: after }
|
|
2035
|
+
);
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
|
|
1929
2039
|
// src/lib/sponsored-deposit.ts
|
|
1930
2040
|
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1931
2041
|
function makeSponsoredDepositCallback(deps) {
|
|
@@ -1941,6 +2051,7 @@ function makeSponsoredDepositCallback(deps) {
|
|
|
1941
2051
|
}
|
|
1942
2052
|
const pub = deps.getPublicClient(cid);
|
|
1943
2053
|
const wallet = deps.getWalletClient(cid);
|
|
2054
|
+
await ensureWalletOnChain(pub, wallet, cid);
|
|
1944
2055
|
try {
|
|
1945
2056
|
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1946
2057
|
if (balance < BigInt(amount)) {
|
|
@@ -1952,6 +2063,10 @@ function makeSponsoredDepositCallback(deps) {
|
|
|
1952
2063
|
}
|
|
1953
2064
|
} catch (err) {
|
|
1954
2065
|
if (err instanceof OwneyError) throw err;
|
|
2066
|
+
console.warn(
|
|
2067
|
+
"[owney-sdk] Deposit balance pre-check failed (non-fatal):",
|
|
2068
|
+
err instanceof Error ? err.message : String(err)
|
|
2069
|
+
);
|
|
1955
2070
|
}
|
|
1956
2071
|
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1957
2072
|
const validAfter = 0n;
|
|
@@ -2015,6 +2130,8 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2015
2130
|
}
|
|
2016
2131
|
const amountWei = BigInt(amount);
|
|
2017
2132
|
const pub = deps.getPublicClient(cid);
|
|
2133
|
+
const wallet = deps.getWalletClient(cid);
|
|
2134
|
+
await ensureWalletOnChain(pub, wallet, cid);
|
|
2018
2135
|
try {
|
|
2019
2136
|
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
2020
2137
|
if (balance < amountWei) {
|
|
@@ -2026,6 +2143,10 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2026
2143
|
}
|
|
2027
2144
|
} catch (err) {
|
|
2028
2145
|
if (err instanceof OwneyError) throw err;
|
|
2146
|
+
console.warn(
|
|
2147
|
+
"[owney-sdk] WETH balance pre-check failed (non-fatal):",
|
|
2148
|
+
err instanceof Error ? err.message : String(err)
|
|
2149
|
+
);
|
|
2029
2150
|
}
|
|
2030
2151
|
const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
|
|
2031
2152
|
if (allowance < amountWei) {
|
|
@@ -2053,7 +2174,6 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2053
2174
|
deadline
|
|
2054
2175
|
}
|
|
2055
2176
|
});
|
|
2056
|
-
const wallet = deps.getWalletClient(cid);
|
|
2057
2177
|
const signature = await wallet.signTypedData({
|
|
2058
2178
|
account: deps.ownerAddress,
|
|
2059
2179
|
...typedData
|
package/dist/index.d.cts
CHANGED
|
@@ -609,7 +609,7 @@ declare class OwneySDK {
|
|
|
609
609
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
610
610
|
}
|
|
611
611
|
|
|
612
|
-
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" | "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";
|
|
612
|
+
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";
|
|
613
613
|
declare class OwneyError extends Error {
|
|
614
614
|
readonly code: OwneyErrorCode;
|
|
615
615
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -609,7 +609,7 @@ declare class OwneySDK {
|
|
|
609
609
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
610
610
|
}
|
|
611
611
|
|
|
612
|
-
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" | "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";
|
|
612
|
+
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";
|
|
613
613
|
declare class OwneyError extends Error {
|
|
614
614
|
readonly code: OwneyErrorCode;
|
|
615
615
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -1285,20 +1285,94 @@ var ZyfaiAgent = class {
|
|
|
1285
1285
|
);
|
|
1286
1286
|
}
|
|
1287
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* True when `smartWallet` is the backend-managed pool wallet Zyfai assigned
|
|
1290
|
+
* to this EOA — the "new wallet" kind that is predeployed on the chains it
|
|
1291
|
+
* was onboarded to. Legacy wallets (created before @zyfai/sdk 0.2.44) have no
|
|
1292
|
+
* pool record.
|
|
1293
|
+
*
|
|
1294
|
+
* A failed lookup returns false rather than throwing: misclassifying is
|
|
1295
|
+
* recoverable (ensureWalletDeployed tries the other deploy call), but
|
|
1296
|
+
* failing the deposit outright is not.
|
|
1297
|
+
*/
|
|
1298
|
+
async isPredeployedPoolWallet(ownerAddress, smartWallet) {
|
|
1299
|
+
try {
|
|
1300
|
+
const byEoa = await this.sdk.getSmartWalletByEOA(ownerAddress);
|
|
1301
|
+
return typeof byEoa?.smartWallet === "string" && byEoa.smartWallet.toLowerCase() === smartWallet.toLowerCase();
|
|
1302
|
+
} catch (error) {
|
|
1303
|
+
console.warn(
|
|
1304
|
+
"[zyfai] getSmartWalletByEOA failed; assuming a legacy wallet:",
|
|
1305
|
+
error instanceof Error ? error.message : String(error)
|
|
1306
|
+
);
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Guarantee the user's Safe has code on `chainId` before anything transfers
|
|
1312
|
+
* funds into it, and return its address.
|
|
1313
|
+
*
|
|
1314
|
+
* Zyfai predeploys wallets created since @zyfai/sdk 0.2.44, but ONLY on the
|
|
1315
|
+
* chains they were onboarded to. Legacy wallets, and any chain a pool wallet
|
|
1316
|
+
* has not been onboarded to, are *counterfactual*: `getSmartWalletAddress`
|
|
1317
|
+
* returns a real deterministic address that holds no code yet. Depositing
|
|
1318
|
+
* there strands the funds until the Safe is deployed, and Owney's own sponsor
|
|
1319
|
+
* relayer refuses to broadcast to an address with no bytecode
|
|
1320
|
+
* (`to-address.guard-helper.ts`), so the deposit fails as an opaque 500.
|
|
1321
|
+
*
|
|
1322
|
+
* ROUT-320 removed the old deploySafe step believing every wallet was
|
|
1323
|
+
* predeployed from 0.2.44 on. Zyf later clarified that only NEW wallets are;
|
|
1324
|
+
* old ones still need the legacy flow. Hence the gate is on the per-chain
|
|
1325
|
+
* `isDeployed` flag rather than on the wallet's age — that covers both a
|
|
1326
|
+
* legacy wallet and a pool wallet on a fresh chain.
|
|
1327
|
+
*/
|
|
1328
|
+
async ensureWalletDeployed(ownerAddress, chainId) {
|
|
1329
|
+
const wallet = await this.sdk.getSmartWalletAddress(ownerAddress, chainId);
|
|
1330
|
+
if (wallet.isDeployed) return wallet.address;
|
|
1331
|
+
const poolFirst = await this.isPredeployedPoolWallet(
|
|
1332
|
+
ownerAddress,
|
|
1333
|
+
wallet.address
|
|
1334
|
+
);
|
|
1335
|
+
const deployAsPool = () => this.sdk.deployOnChains([chainId]);
|
|
1336
|
+
const deployAsLegacy = () => (
|
|
1337
|
+
// `createSessionKey: false` — session keys are backend-owned since the
|
|
1338
|
+
// predeployed-pool rollout; asking for one here costs a signature prompt
|
|
1339
|
+
// and is rejected anyway.
|
|
1340
|
+
this.sdk.deploySafe(ownerAddress, chainId, "aggressive", false)
|
|
1341
|
+
);
|
|
1342
|
+
const [first, second] = poolFirst ? [deployAsPool, deployAsLegacy] : [deployAsLegacy, deployAsPool];
|
|
1343
|
+
try {
|
|
1344
|
+
await first();
|
|
1345
|
+
} catch (error) {
|
|
1346
|
+
console.warn(
|
|
1347
|
+
`[zyfai] ${poolFirst ? "deployOnChains" : "deploySafe"} failed on chain ${chainId}; trying the other deploy path:`,
|
|
1348
|
+
error instanceof Error ? error.message : String(error)
|
|
1349
|
+
);
|
|
1350
|
+
await second();
|
|
1351
|
+
}
|
|
1352
|
+
const redeployed = await this.sdk.getSmartWalletAddress(
|
|
1353
|
+
ownerAddress,
|
|
1354
|
+
chainId
|
|
1355
|
+
);
|
|
1356
|
+
if (!redeployed.isDeployed) {
|
|
1357
|
+
throw new OwneyError(
|
|
1358
|
+
"WALLET_NOT_DEPLOYED",
|
|
1359
|
+
`Smart wallet ${redeployed.address} is still not deployed on chain ${chainId}. Depositing would send funds to an address with no code.`,
|
|
1360
|
+
{ chainId, smartWallet: redeployed.address },
|
|
1361
|
+
this.id
|
|
1362
|
+
);
|
|
1363
|
+
}
|
|
1364
|
+
return redeployed.address;
|
|
1365
|
+
}
|
|
1288
1366
|
async deposit(state, chainId, amount, asset, depositCallback) {
|
|
1289
1367
|
try {
|
|
1290
1368
|
const validChainId = isValidChainId(chainId);
|
|
1291
1369
|
await this.ensureConnected(state, validChainId);
|
|
1292
1370
|
if (depositCallback) {
|
|
1293
|
-
const
|
|
1371
|
+
const smartWallet = await this.ensureWalletDeployed(
|
|
1294
1372
|
this.getAddress(),
|
|
1295
1373
|
validChainId
|
|
1296
1374
|
);
|
|
1297
|
-
const txHash = await depositCallback(
|
|
1298
|
-
wallet.address,
|
|
1299
|
-
validChainId,
|
|
1300
|
-
amount
|
|
1301
|
-
);
|
|
1375
|
+
const txHash = await depositCallback(smartWallet, validChainId, amount);
|
|
1302
1376
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
1303
1377
|
try {
|
|
1304
1378
|
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
@@ -1308,8 +1382,9 @@ var ZyfaiAgent = class {
|
|
|
1308
1382
|
logError
|
|
1309
1383
|
);
|
|
1310
1384
|
}
|
|
1311
|
-
return { txHash, smartWallet
|
|
1385
|
+
return { txHash, smartWallet, amount };
|
|
1312
1386
|
}
|
|
1387
|
+
await this.ensureWalletDeployed(this.getAddress(), validChainId);
|
|
1313
1388
|
const raw = await this.sdk.depositFunds(
|
|
1314
1389
|
this.getAddress(),
|
|
1315
1390
|
validChainId,
|
|
@@ -1897,6 +1972,41 @@ async function readErc20Balance(publicClient, token, owner) {
|
|
|
1897
1972
|
});
|
|
1898
1973
|
}
|
|
1899
1974
|
|
|
1975
|
+
// src/lib/chain-guard.ts
|
|
1976
|
+
var CHAIN_NAMES = {
|
|
1977
|
+
1: "Ethereum",
|
|
1978
|
+
8453: "Base",
|
|
1979
|
+
42161: "Arbitrum"
|
|
1980
|
+
};
|
|
1981
|
+
function chainName(chainId) {
|
|
1982
|
+
return CHAIN_NAMES[chainId] ?? `chain ${chainId}`;
|
|
1983
|
+
}
|
|
1984
|
+
async function ensureWalletOnChain(pub, wallet, expected) {
|
|
1985
|
+
const actual = await pub.getChainId();
|
|
1986
|
+
if (actual === expected) return;
|
|
1987
|
+
try {
|
|
1988
|
+
await wallet.switchChain({ id: expected });
|
|
1989
|
+
} catch (error) {
|
|
1990
|
+
throw new OwneyError(
|
|
1991
|
+
"CHAIN_MISMATCH",
|
|
1992
|
+
`Your wallet is on ${chainName(actual)}. Switch it to ${chainName(expected)} and try again.`,
|
|
1993
|
+
{
|
|
1994
|
+
expectedChainId: expected,
|
|
1995
|
+
actualChainId: actual,
|
|
1996
|
+
cause: error instanceof Error ? error.message : String(error)
|
|
1997
|
+
}
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
const after = await pub.getChainId();
|
|
2001
|
+
if (after !== expected) {
|
|
2002
|
+
throw new OwneyError(
|
|
2003
|
+
"CHAIN_MISMATCH",
|
|
2004
|
+
`Your wallet is still on ${chainName(after)}. Switch it to ${chainName(expected)} and try again.`,
|
|
2005
|
+
{ expectedChainId: expected, actualChainId: after }
|
|
2006
|
+
);
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
|
|
1900
2010
|
// src/lib/sponsored-deposit.ts
|
|
1901
2011
|
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1902
2012
|
function makeSponsoredDepositCallback(deps) {
|
|
@@ -1912,6 +2022,7 @@ function makeSponsoredDepositCallback(deps) {
|
|
|
1912
2022
|
}
|
|
1913
2023
|
const pub = deps.getPublicClient(cid);
|
|
1914
2024
|
const wallet = deps.getWalletClient(cid);
|
|
2025
|
+
await ensureWalletOnChain(pub, wallet, cid);
|
|
1915
2026
|
try {
|
|
1916
2027
|
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1917
2028
|
if (balance < BigInt(amount)) {
|
|
@@ -1923,6 +2034,10 @@ function makeSponsoredDepositCallback(deps) {
|
|
|
1923
2034
|
}
|
|
1924
2035
|
} catch (err) {
|
|
1925
2036
|
if (err instanceof OwneyError) throw err;
|
|
2037
|
+
console.warn(
|
|
2038
|
+
"[owney-sdk] Deposit balance pre-check failed (non-fatal):",
|
|
2039
|
+
err instanceof Error ? err.message : String(err)
|
|
2040
|
+
);
|
|
1926
2041
|
}
|
|
1927
2042
|
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1928
2043
|
const validAfter = 0n;
|
|
@@ -1986,6 +2101,8 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1986
2101
|
}
|
|
1987
2102
|
const amountWei = BigInt(amount);
|
|
1988
2103
|
const pub = deps.getPublicClient(cid);
|
|
2104
|
+
const wallet = deps.getWalletClient(cid);
|
|
2105
|
+
await ensureWalletOnChain(pub, wallet, cid);
|
|
1989
2106
|
try {
|
|
1990
2107
|
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1991
2108
|
if (balance < amountWei) {
|
|
@@ -1997,6 +2114,10 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1997
2114
|
}
|
|
1998
2115
|
} catch (err) {
|
|
1999
2116
|
if (err instanceof OwneyError) throw err;
|
|
2117
|
+
console.warn(
|
|
2118
|
+
"[owney-sdk] WETH balance pre-check failed (non-fatal):",
|
|
2119
|
+
err instanceof Error ? err.message : String(err)
|
|
2120
|
+
);
|
|
2000
2121
|
}
|
|
2001
2122
|
const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
|
|
2002
2123
|
if (allowance < amountWei) {
|
|
@@ -2024,7 +2145,6 @@ function makeSponsoredWethCallback(deps) {
|
|
|
2024
2145
|
deadline
|
|
2025
2146
|
}
|
|
2026
2147
|
});
|
|
2027
|
-
const wallet = deps.getWalletClient(cid);
|
|
2028
2148
|
const signature = await wallet.signTypedData({
|
|
2029
2149
|
account: deps.ownerAddress,
|
|
2030
2150
|
...typedData
|