@owney/sdk 0.6.8-beta.1 → 0.6.8-beta.3
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 +153 -70
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +153 -70
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1051,7 +1051,14 @@ var ZyfaiAgent = class {
|
|
|
1051
1051
|
amount
|
|
1052
1052
|
);
|
|
1053
1053
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
1054
|
-
|
|
1054
|
+
try {
|
|
1055
|
+
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
1056
|
+
} catch (logError) {
|
|
1057
|
+
console.warn(
|
|
1058
|
+
"[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
|
|
1059
|
+
logError
|
|
1060
|
+
);
|
|
1061
|
+
}
|
|
1055
1062
|
return { txHash, smartWallet: wallet.address, amount };
|
|
1056
1063
|
}
|
|
1057
1064
|
const raw = await this.sdk.depositFunds(
|
|
@@ -1516,56 +1523,6 @@ async function getSponsorRelayerAddress(input) {
|
|
|
1516
1523
|
return parsed.data.relayer;
|
|
1517
1524
|
}
|
|
1518
1525
|
|
|
1519
|
-
// src/lib/sponsored-deposit.ts
|
|
1520
|
-
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1521
|
-
function makeSponsoredDepositCallback(deps) {
|
|
1522
|
-
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1523
|
-
return async (smartWallet, chainId, amount) => {
|
|
1524
|
-
const cid = chainId;
|
|
1525
|
-
const token = deps.tokenAddressByChain[cid];
|
|
1526
|
-
if (!token) {
|
|
1527
|
-
throw new OwneyError(
|
|
1528
|
-
"CHAIN_UNSUPPORTED",
|
|
1529
|
-
`No sponsored token configured for chain ${chainId}`
|
|
1530
|
-
);
|
|
1531
|
-
}
|
|
1532
|
-
const pub = deps.getPublicClient(cid);
|
|
1533
|
-
const wallet = deps.getWalletClient(cid);
|
|
1534
|
-
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1535
|
-
const validAfter = 0n;
|
|
1536
|
-
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1537
|
-
const nonce = randomAuthNonce();
|
|
1538
|
-
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1539
|
-
token,
|
|
1540
|
-
chainId: cid,
|
|
1541
|
-
tokenName,
|
|
1542
|
-
tokenVersion,
|
|
1543
|
-
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1544
|
-
});
|
|
1545
|
-
const authSignature = await wallet.signTypedData(
|
|
1546
|
-
{ account: deps.ownerAddress, ...typedData }
|
|
1547
|
-
);
|
|
1548
|
-
const result = await post({
|
|
1549
|
-
baseUrl: deps.baseUrl,
|
|
1550
|
-
apiKey: deps.apiKey,
|
|
1551
|
-
body: {
|
|
1552
|
-
chainId: cid,
|
|
1553
|
-
token,
|
|
1554
|
-
from: deps.ownerAddress,
|
|
1555
|
-
to: smartWallet,
|
|
1556
|
-
value: amount,
|
|
1557
|
-
validAfter: validAfter.toString(),
|
|
1558
|
-
validBefore: validBefore.toString(),
|
|
1559
|
-
nonce,
|
|
1560
|
-
authSignature,
|
|
1561
|
-
tokenName,
|
|
1562
|
-
tokenVersion
|
|
1563
|
-
}
|
|
1564
|
-
});
|
|
1565
|
-
return result.txHash;
|
|
1566
|
-
};
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
1526
|
// src/lib/permit2.ts
|
|
1570
1527
|
var import_viem4 = require("viem");
|
|
1571
1528
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
@@ -1575,20 +1532,37 @@ var ERC20_ALLOWANCE_ABI = [
|
|
|
1575
1532
|
type: "function",
|
|
1576
1533
|
name: "allowance",
|
|
1577
1534
|
stateMutability: "view",
|
|
1578
|
-
inputs: [
|
|
1535
|
+
inputs: [
|
|
1536
|
+
{ name: "owner", type: "address" },
|
|
1537
|
+
{ name: "spender", type: "address" }
|
|
1538
|
+
],
|
|
1579
1539
|
outputs: [{ name: "", type: "uint256" }]
|
|
1580
1540
|
},
|
|
1581
1541
|
{
|
|
1582
1542
|
type: "function",
|
|
1583
1543
|
name: "approve",
|
|
1584
1544
|
stateMutability: "nonpayable",
|
|
1585
|
-
inputs: [
|
|
1545
|
+
inputs: [
|
|
1546
|
+
{ name: "spender", type: "address" },
|
|
1547
|
+
{ name: "amount", type: "uint256" }
|
|
1548
|
+
],
|
|
1586
1549
|
outputs: [{ name: "", type: "bool" }]
|
|
1550
|
+
},
|
|
1551
|
+
{
|
|
1552
|
+
type: "function",
|
|
1553
|
+
name: "balanceOf",
|
|
1554
|
+
stateMutability: "view",
|
|
1555
|
+
inputs: [{ name: "account", type: "address" }],
|
|
1556
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
1587
1557
|
}
|
|
1588
1558
|
];
|
|
1589
1559
|
function buildPermitTransferFromTypedData(input) {
|
|
1590
1560
|
return {
|
|
1591
|
-
domain: {
|
|
1561
|
+
domain: {
|
|
1562
|
+
name: "Permit2",
|
|
1563
|
+
chainId: input.chainId,
|
|
1564
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
1565
|
+
},
|
|
1592
1566
|
types: {
|
|
1593
1567
|
PermitTransferFrom: [
|
|
1594
1568
|
{ name: "permitted", type: "TokenPermissions" },
|
|
@@ -1618,6 +1592,87 @@ async function readPermit2Allowance(publicClient, token, owner) {
|
|
|
1618
1592
|
args: [owner, PERMIT2_ADDRESS]
|
|
1619
1593
|
});
|
|
1620
1594
|
}
|
|
1595
|
+
async function readErc20Balance(publicClient, token, owner) {
|
|
1596
|
+
return publicClient.readContract({
|
|
1597
|
+
address: token,
|
|
1598
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
1599
|
+
functionName: "balanceOf",
|
|
1600
|
+
args: [owner]
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
// src/lib/sponsored-deposit.ts
|
|
1605
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1606
|
+
function makeSponsoredDepositCallback(deps) {
|
|
1607
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1608
|
+
return async (smartWallet, chainId, amount) => {
|
|
1609
|
+
const cid = chainId;
|
|
1610
|
+
const token = deps.tokenAddressByChain[cid];
|
|
1611
|
+
if (!token) {
|
|
1612
|
+
throw new OwneyError(
|
|
1613
|
+
"CHAIN_UNSUPPORTED",
|
|
1614
|
+
`No sponsored token configured for chain ${chainId}`
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
const pub = deps.getPublicClient(cid);
|
|
1618
|
+
const wallet = deps.getWalletClient(cid);
|
|
1619
|
+
try {
|
|
1620
|
+
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1621
|
+
if (balance < BigInt(amount)) {
|
|
1622
|
+
throw new OwneyError(
|
|
1623
|
+
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
1624
|
+
"Insufficient balance for this deposit.",
|
|
1625
|
+
{ token, chainId: cid, balance: balance.toString(), amount }
|
|
1626
|
+
);
|
|
1627
|
+
}
|
|
1628
|
+
} catch (err) {
|
|
1629
|
+
if (err instanceof OwneyError) throw err;
|
|
1630
|
+
}
|
|
1631
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1632
|
+
const validAfter = 0n;
|
|
1633
|
+
const validBefore = BigInt(
|
|
1634
|
+
Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
|
|
1635
|
+
);
|
|
1636
|
+
const nonce = randomAuthNonce();
|
|
1637
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1638
|
+
token,
|
|
1639
|
+
chainId: cid,
|
|
1640
|
+
tokenName,
|
|
1641
|
+
tokenVersion,
|
|
1642
|
+
message: {
|
|
1643
|
+
from: deps.ownerAddress,
|
|
1644
|
+
to: smartWallet,
|
|
1645
|
+
value: BigInt(amount),
|
|
1646
|
+
validAfter,
|
|
1647
|
+
validBefore,
|
|
1648
|
+
nonce
|
|
1649
|
+
}
|
|
1650
|
+
});
|
|
1651
|
+
const authSignature = await wallet.signTypedData({
|
|
1652
|
+
account: deps.ownerAddress,
|
|
1653
|
+
...typedData
|
|
1654
|
+
});
|
|
1655
|
+
deps.onApproved?.();
|
|
1656
|
+
const result = await post({
|
|
1657
|
+
baseUrl: deps.baseUrl,
|
|
1658
|
+
apiKey: deps.apiKey,
|
|
1659
|
+
body: {
|
|
1660
|
+
chainId: cid,
|
|
1661
|
+
token,
|
|
1662
|
+
from: deps.ownerAddress,
|
|
1663
|
+
to: smartWallet,
|
|
1664
|
+
value: amount,
|
|
1665
|
+
validAfter: validAfter.toString(),
|
|
1666
|
+
validBefore: validBefore.toString(),
|
|
1667
|
+
nonce,
|
|
1668
|
+
authSignature,
|
|
1669
|
+
tokenName,
|
|
1670
|
+
tokenVersion
|
|
1671
|
+
}
|
|
1672
|
+
});
|
|
1673
|
+
return result.txHash;
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1621
1676
|
|
|
1622
1677
|
// src/lib/sponsored-weth-deposit.ts
|
|
1623
1678
|
var PERMIT_WINDOW_SECONDS = 15 * 60;
|
|
@@ -1628,10 +1683,25 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1628
1683
|
const cid = chainId;
|
|
1629
1684
|
const token = deps.tokenAddressByChain[cid];
|
|
1630
1685
|
if (!token) {
|
|
1631
|
-
throw new OwneyError(
|
|
1686
|
+
throw new OwneyError(
|
|
1687
|
+
"CHAIN_UNSUPPORTED",
|
|
1688
|
+
`No sponsored WETH configured for chain ${chainId}`
|
|
1689
|
+
);
|
|
1632
1690
|
}
|
|
1633
1691
|
const amountWei = BigInt(amount);
|
|
1634
1692
|
const pub = deps.getPublicClient(cid);
|
|
1693
|
+
try {
|
|
1694
|
+
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1695
|
+
if (balance < amountWei) {
|
|
1696
|
+
throw new OwneyError(
|
|
1697
|
+
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
1698
|
+
"Insufficient WETH balance for this deposit.",
|
|
1699
|
+
{ token, chainId: cid, balance: balance.toString(), amount }
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
} catch (err) {
|
|
1703
|
+
if (err instanceof OwneyError) throw err;
|
|
1704
|
+
}
|
|
1635
1705
|
const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
|
|
1636
1706
|
if (allowance < amountWei) {
|
|
1637
1707
|
throw new OwneyError(
|
|
@@ -1640,9 +1710,15 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1640
1710
|
{ token, chainId: cid, allowance: allowance.toString(), amount }
|
|
1641
1711
|
);
|
|
1642
1712
|
}
|
|
1643
|
-
const relayer = await get({
|
|
1713
|
+
const relayer = await get({
|
|
1714
|
+
baseUrl: deps.baseUrl,
|
|
1715
|
+
apiKey: deps.apiKey,
|
|
1716
|
+
chainId: cid
|
|
1717
|
+
});
|
|
1644
1718
|
const nonce = randomPermit2Nonce();
|
|
1645
|
-
const deadline = BigInt(
|
|
1719
|
+
const deadline = BigInt(
|
|
1720
|
+
Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
|
|
1721
|
+
);
|
|
1646
1722
|
const typedData = buildPermitTransferFromTypedData({
|
|
1647
1723
|
chainId: cid,
|
|
1648
1724
|
message: {
|
|
@@ -1653,9 +1729,11 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1653
1729
|
}
|
|
1654
1730
|
});
|
|
1655
1731
|
const wallet = deps.getWalletClient(cid);
|
|
1656
|
-
const signature = await wallet.signTypedData(
|
|
1657
|
-
|
|
1658
|
-
|
|
1732
|
+
const signature = await wallet.signTypedData({
|
|
1733
|
+
account: deps.ownerAddress,
|
|
1734
|
+
...typedData
|
|
1735
|
+
});
|
|
1736
|
+
deps.onApproved?.();
|
|
1659
1737
|
const result = await post({
|
|
1660
1738
|
baseUrl: deps.baseUrl,
|
|
1661
1739
|
apiKey: deps.apiKey,
|
|
@@ -1818,14 +1896,16 @@ var OwneySDK = class {
|
|
|
1818
1896
|
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1819
1897
|
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1820
1898
|
*/
|
|
1821
|
-
getDefaultSponsoredCallback() {
|
|
1822
|
-
if (
|
|
1899
|
+
getDefaultSponsoredCallback(onApproved) {
|
|
1900
|
+
if (!onApproved && this.cachedSponsoredCallback)
|
|
1901
|
+
return this.cachedSponsoredCallback;
|
|
1823
1902
|
const provider = this.requireConnectedProvider();
|
|
1824
1903
|
const owner = this.state.walletAddress;
|
|
1825
|
-
|
|
1904
|
+
const callback = makeSponsoredDepositCallback({
|
|
1826
1905
|
apiKey: this.apiKey,
|
|
1827
1906
|
baseUrl: this.routingApiBaseUrl,
|
|
1828
1907
|
ownerAddress: owner,
|
|
1908
|
+
onApproved,
|
|
1829
1909
|
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1830
1910
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1831
1911
|
// PublicClient/WalletClient param types — structurally identical at
|
|
@@ -1840,7 +1920,8 @@ var OwneySDK = class {
|
|
|
1840
1920
|
transport: (0, import_viem5.custom)(provider)
|
|
1841
1921
|
})
|
|
1842
1922
|
});
|
|
1843
|
-
|
|
1923
|
+
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
1924
|
+
return callback;
|
|
1844
1925
|
}
|
|
1845
1926
|
/**
|
|
1846
1927
|
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
@@ -1848,15 +1929,16 @@ var OwneySDK = class {
|
|
|
1848
1929
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
1849
1930
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
1850
1931
|
*/
|
|
1851
|
-
getDefaultWethSponsoredCallback() {
|
|
1852
|
-
if (this.cachedWethSponsoredCallback)
|
|
1932
|
+
getDefaultWethSponsoredCallback(onApproved) {
|
|
1933
|
+
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
1853
1934
|
return this.cachedWethSponsoredCallback;
|
|
1854
1935
|
const provider = this.requireConnectedProvider();
|
|
1855
1936
|
const owner = this.state.walletAddress;
|
|
1856
|
-
|
|
1937
|
+
const callback = makeSponsoredWethCallback({
|
|
1857
1938
|
apiKey: this.apiKey,
|
|
1858
1939
|
baseUrl: this.routingApiBaseUrl,
|
|
1859
1940
|
ownerAddress: owner,
|
|
1941
|
+
onApproved,
|
|
1860
1942
|
tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
|
|
1861
1943
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1862
1944
|
// PublicClient/WalletClient param types — structurally identical at
|
|
@@ -1871,7 +1953,8 @@ var OwneySDK = class {
|
|
|
1871
1953
|
transport: (0, import_viem5.custom)(provider)
|
|
1872
1954
|
})
|
|
1873
1955
|
});
|
|
1874
|
-
|
|
1956
|
+
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
1957
|
+
return callback;
|
|
1875
1958
|
}
|
|
1876
1959
|
getAgent(agentId) {
|
|
1877
1960
|
const agent = this.agents.get(agentId);
|
|
@@ -2017,13 +2100,13 @@ var OwneySDK = class {
|
|
|
2017
2100
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
2018
2101
|
*/
|
|
2019
2102
|
async deposit(options) {
|
|
2020
|
-
const { amount, asset, depositCallback, agentId } = options;
|
|
2103
|
+
const { amount, asset, depositCallback, agentId, onApproved } = options;
|
|
2021
2104
|
if (BigInt(amount) === 0n) {
|
|
2022
2105
|
return { agentResults: {} };
|
|
2023
2106
|
}
|
|
2024
2107
|
const state = this.requireState();
|
|
2025
2108
|
const chainId = this.requireChainId();
|
|
2026
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback() : this.getDefaultSponsoredCallback());
|
|
2109
|
+
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
2027
2110
|
if (agentId) {
|
|
2028
2111
|
if (this.isAgentDisabled(agentId)) {
|
|
2029
2112
|
throw new OwneyError(
|
package/dist/index.d.cts
CHANGED
|
@@ -98,6 +98,7 @@ type DepositOptions = {
|
|
|
98
98
|
asset: Asset;
|
|
99
99
|
depositCallback?: DepositCallback;
|
|
100
100
|
agentId?: AgentId;
|
|
101
|
+
onApproved?: () => void;
|
|
101
102
|
};
|
|
102
103
|
|
|
103
104
|
interface OwneyDepositResult {
|
|
@@ -524,7 +525,7 @@ declare class OwneySDK {
|
|
|
524
525
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
525
526
|
}
|
|
526
527
|
|
|
527
|
-
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" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
528
|
+
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";
|
|
528
529
|
declare class OwneyError extends Error {
|
|
529
530
|
readonly code: OwneyErrorCode;
|
|
530
531
|
readonly details?: Record<string, unknown>;
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ type DepositOptions = {
|
|
|
98
98
|
asset: Asset;
|
|
99
99
|
depositCallback?: DepositCallback;
|
|
100
100
|
agentId?: AgentId;
|
|
101
|
+
onApproved?: () => void;
|
|
101
102
|
};
|
|
102
103
|
|
|
103
104
|
interface OwneyDepositResult {
|
|
@@ -524,7 +525,7 @@ declare class OwneySDK {
|
|
|
524
525
|
getAllocationApy({ agentId, }?: AllocationApyOptions): Promise<OwneyAllocationApy>;
|
|
525
526
|
}
|
|
526
527
|
|
|
527
|
-
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" | "PERMIT2_APPROVAL_REQUIRED" | "BALANCE_ALL_FAILED" | "ALLOCATION_ALL_FAILED" | "VALIDATION_INVALID_DAYS";
|
|
528
|
+
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";
|
|
528
529
|
declare class OwneyError extends Error {
|
|
529
530
|
readonly code: OwneyErrorCode;
|
|
530
531
|
readonly details?: Record<string, unknown>;
|
package/dist/index.js
CHANGED
|
@@ -1019,7 +1019,14 @@ var ZyfaiAgent = class {
|
|
|
1019
1019
|
amount
|
|
1020
1020
|
);
|
|
1021
1021
|
const tokenAddress = asset === "WETH" ? WETH_ADDRESS_BY_CHAIN[validChainId] : void 0;
|
|
1022
|
-
|
|
1022
|
+
try {
|
|
1023
|
+
await (tokenAddress ? this.sdk.logDeposit(validChainId, txHash, amount, tokenAddress) : this.sdk.logDeposit(validChainId, txHash, amount));
|
|
1024
|
+
} catch (logError) {
|
|
1025
|
+
console.warn(
|
|
1026
|
+
"[owney-sdk] Deposit landed on-chain but logDeposit failed (non-fatal):",
|
|
1027
|
+
logError
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1023
1030
|
return { txHash, smartWallet: wallet.address, amount };
|
|
1024
1031
|
}
|
|
1025
1032
|
const raw = await this.sdk.depositFunds(
|
|
@@ -1488,56 +1495,6 @@ async function getSponsorRelayerAddress(input) {
|
|
|
1488
1495
|
return parsed.data.relayer;
|
|
1489
1496
|
}
|
|
1490
1497
|
|
|
1491
|
-
// src/lib/sponsored-deposit.ts
|
|
1492
|
-
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1493
|
-
function makeSponsoredDepositCallback(deps) {
|
|
1494
|
-
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1495
|
-
return async (smartWallet, chainId, amount) => {
|
|
1496
|
-
const cid = chainId;
|
|
1497
|
-
const token = deps.tokenAddressByChain[cid];
|
|
1498
|
-
if (!token) {
|
|
1499
|
-
throw new OwneyError(
|
|
1500
|
-
"CHAIN_UNSUPPORTED",
|
|
1501
|
-
`No sponsored token configured for chain ${chainId}`
|
|
1502
|
-
);
|
|
1503
|
-
}
|
|
1504
|
-
const pub = deps.getPublicClient(cid);
|
|
1505
|
-
const wallet = deps.getWalletClient(cid);
|
|
1506
|
-
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1507
|
-
const validAfter = 0n;
|
|
1508
|
-
const validBefore = BigInt(Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS);
|
|
1509
|
-
const nonce = randomAuthNonce();
|
|
1510
|
-
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1511
|
-
token,
|
|
1512
|
-
chainId: cid,
|
|
1513
|
-
tokenName,
|
|
1514
|
-
tokenVersion,
|
|
1515
|
-
message: { from: deps.ownerAddress, to: smartWallet, value: BigInt(amount), validAfter, validBefore, nonce }
|
|
1516
|
-
});
|
|
1517
|
-
const authSignature = await wallet.signTypedData(
|
|
1518
|
-
{ account: deps.ownerAddress, ...typedData }
|
|
1519
|
-
);
|
|
1520
|
-
const result = await post({
|
|
1521
|
-
baseUrl: deps.baseUrl,
|
|
1522
|
-
apiKey: deps.apiKey,
|
|
1523
|
-
body: {
|
|
1524
|
-
chainId: cid,
|
|
1525
|
-
token,
|
|
1526
|
-
from: deps.ownerAddress,
|
|
1527
|
-
to: smartWallet,
|
|
1528
|
-
value: amount,
|
|
1529
|
-
validAfter: validAfter.toString(),
|
|
1530
|
-
validBefore: validBefore.toString(),
|
|
1531
|
-
nonce,
|
|
1532
|
-
authSignature,
|
|
1533
|
-
tokenName,
|
|
1534
|
-
tokenVersion
|
|
1535
|
-
}
|
|
1536
|
-
});
|
|
1537
|
-
return result.txHash;
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
|
|
1541
1498
|
// src/lib/permit2.ts
|
|
1542
1499
|
import { bytesToHex as bytesToHex2 } from "viem";
|
|
1543
1500
|
var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3";
|
|
@@ -1547,20 +1504,37 @@ var ERC20_ALLOWANCE_ABI = [
|
|
|
1547
1504
|
type: "function",
|
|
1548
1505
|
name: "allowance",
|
|
1549
1506
|
stateMutability: "view",
|
|
1550
|
-
inputs: [
|
|
1507
|
+
inputs: [
|
|
1508
|
+
{ name: "owner", type: "address" },
|
|
1509
|
+
{ name: "spender", type: "address" }
|
|
1510
|
+
],
|
|
1551
1511
|
outputs: [{ name: "", type: "uint256" }]
|
|
1552
1512
|
},
|
|
1553
1513
|
{
|
|
1554
1514
|
type: "function",
|
|
1555
1515
|
name: "approve",
|
|
1556
1516
|
stateMutability: "nonpayable",
|
|
1557
|
-
inputs: [
|
|
1517
|
+
inputs: [
|
|
1518
|
+
{ name: "spender", type: "address" },
|
|
1519
|
+
{ name: "amount", type: "uint256" }
|
|
1520
|
+
],
|
|
1558
1521
|
outputs: [{ name: "", type: "bool" }]
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
type: "function",
|
|
1525
|
+
name: "balanceOf",
|
|
1526
|
+
stateMutability: "view",
|
|
1527
|
+
inputs: [{ name: "account", type: "address" }],
|
|
1528
|
+
outputs: [{ name: "", type: "uint256" }]
|
|
1559
1529
|
}
|
|
1560
1530
|
];
|
|
1561
1531
|
function buildPermitTransferFromTypedData(input) {
|
|
1562
1532
|
return {
|
|
1563
|
-
domain: {
|
|
1533
|
+
domain: {
|
|
1534
|
+
name: "Permit2",
|
|
1535
|
+
chainId: input.chainId,
|
|
1536
|
+
verifyingContract: PERMIT2_ADDRESS
|
|
1537
|
+
},
|
|
1564
1538
|
types: {
|
|
1565
1539
|
PermitTransferFrom: [
|
|
1566
1540
|
{ name: "permitted", type: "TokenPermissions" },
|
|
@@ -1590,6 +1564,87 @@ async function readPermit2Allowance(publicClient, token, owner) {
|
|
|
1590
1564
|
args: [owner, PERMIT2_ADDRESS]
|
|
1591
1565
|
});
|
|
1592
1566
|
}
|
|
1567
|
+
async function readErc20Balance(publicClient, token, owner) {
|
|
1568
|
+
return publicClient.readContract({
|
|
1569
|
+
address: token,
|
|
1570
|
+
abi: ERC20_ALLOWANCE_ABI,
|
|
1571
|
+
functionName: "balanceOf",
|
|
1572
|
+
args: [owner]
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
// src/lib/sponsored-deposit.ts
|
|
1577
|
+
var AUTH_WINDOW_SECONDS = 15 * 60;
|
|
1578
|
+
function makeSponsoredDepositCallback(deps) {
|
|
1579
|
+
const post = deps.httpPost ?? postSponsorTransferAuth;
|
|
1580
|
+
return async (smartWallet, chainId, amount) => {
|
|
1581
|
+
const cid = chainId;
|
|
1582
|
+
const token = deps.tokenAddressByChain[cid];
|
|
1583
|
+
if (!token) {
|
|
1584
|
+
throw new OwneyError(
|
|
1585
|
+
"CHAIN_UNSUPPORTED",
|
|
1586
|
+
`No sponsored token configured for chain ${chainId}`
|
|
1587
|
+
);
|
|
1588
|
+
}
|
|
1589
|
+
const pub = deps.getPublicClient(cid);
|
|
1590
|
+
const wallet = deps.getWalletClient(cid);
|
|
1591
|
+
try {
|
|
1592
|
+
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1593
|
+
if (balance < BigInt(amount)) {
|
|
1594
|
+
throw new OwneyError(
|
|
1595
|
+
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
1596
|
+
"Insufficient balance for this deposit.",
|
|
1597
|
+
{ token, chainId: cid, balance: balance.toString(), amount }
|
|
1598
|
+
);
|
|
1599
|
+
}
|
|
1600
|
+
} catch (err) {
|
|
1601
|
+
if (err instanceof OwneyError) throw err;
|
|
1602
|
+
}
|
|
1603
|
+
const { tokenName, tokenVersion } = await readTokenMeta(pub, token);
|
|
1604
|
+
const validAfter = 0n;
|
|
1605
|
+
const validBefore = BigInt(
|
|
1606
|
+
Math.floor(Date.now() / 1e3) + AUTH_WINDOW_SECONDS
|
|
1607
|
+
);
|
|
1608
|
+
const nonce = randomAuthNonce();
|
|
1609
|
+
const typedData = buildTransferWithAuthorizationTypedData({
|
|
1610
|
+
token,
|
|
1611
|
+
chainId: cid,
|
|
1612
|
+
tokenName,
|
|
1613
|
+
tokenVersion,
|
|
1614
|
+
message: {
|
|
1615
|
+
from: deps.ownerAddress,
|
|
1616
|
+
to: smartWallet,
|
|
1617
|
+
value: BigInt(amount),
|
|
1618
|
+
validAfter,
|
|
1619
|
+
validBefore,
|
|
1620
|
+
nonce
|
|
1621
|
+
}
|
|
1622
|
+
});
|
|
1623
|
+
const authSignature = await wallet.signTypedData({
|
|
1624
|
+
account: deps.ownerAddress,
|
|
1625
|
+
...typedData
|
|
1626
|
+
});
|
|
1627
|
+
deps.onApproved?.();
|
|
1628
|
+
const result = await post({
|
|
1629
|
+
baseUrl: deps.baseUrl,
|
|
1630
|
+
apiKey: deps.apiKey,
|
|
1631
|
+
body: {
|
|
1632
|
+
chainId: cid,
|
|
1633
|
+
token,
|
|
1634
|
+
from: deps.ownerAddress,
|
|
1635
|
+
to: smartWallet,
|
|
1636
|
+
value: amount,
|
|
1637
|
+
validAfter: validAfter.toString(),
|
|
1638
|
+
validBefore: validBefore.toString(),
|
|
1639
|
+
nonce,
|
|
1640
|
+
authSignature,
|
|
1641
|
+
tokenName,
|
|
1642
|
+
tokenVersion
|
|
1643
|
+
}
|
|
1644
|
+
});
|
|
1645
|
+
return result.txHash;
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1593
1648
|
|
|
1594
1649
|
// src/lib/sponsored-weth-deposit.ts
|
|
1595
1650
|
var PERMIT_WINDOW_SECONDS = 15 * 60;
|
|
@@ -1600,10 +1655,25 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1600
1655
|
const cid = chainId;
|
|
1601
1656
|
const token = deps.tokenAddressByChain[cid];
|
|
1602
1657
|
if (!token) {
|
|
1603
|
-
throw new OwneyError(
|
|
1658
|
+
throw new OwneyError(
|
|
1659
|
+
"CHAIN_UNSUPPORTED",
|
|
1660
|
+
`No sponsored WETH configured for chain ${chainId}`
|
|
1661
|
+
);
|
|
1604
1662
|
}
|
|
1605
1663
|
const amountWei = BigInt(amount);
|
|
1606
1664
|
const pub = deps.getPublicClient(cid);
|
|
1665
|
+
try {
|
|
1666
|
+
const balance = await readErc20Balance(pub, token, deps.ownerAddress);
|
|
1667
|
+
if (balance < amountWei) {
|
|
1668
|
+
throw new OwneyError(
|
|
1669
|
+
"DEPOSIT_INSUFFICIENT_BALANCE",
|
|
1670
|
+
"Insufficient WETH balance for this deposit.",
|
|
1671
|
+
{ token, chainId: cid, balance: balance.toString(), amount }
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
} catch (err) {
|
|
1675
|
+
if (err instanceof OwneyError) throw err;
|
|
1676
|
+
}
|
|
1607
1677
|
const allowance = await readPermit2Allowance(pub, token, deps.ownerAddress);
|
|
1608
1678
|
if (allowance < amountWei) {
|
|
1609
1679
|
throw new OwneyError(
|
|
@@ -1612,9 +1682,15 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1612
1682
|
{ token, chainId: cid, allowance: allowance.toString(), amount }
|
|
1613
1683
|
);
|
|
1614
1684
|
}
|
|
1615
|
-
const relayer = await get({
|
|
1685
|
+
const relayer = await get({
|
|
1686
|
+
baseUrl: deps.baseUrl,
|
|
1687
|
+
apiKey: deps.apiKey,
|
|
1688
|
+
chainId: cid
|
|
1689
|
+
});
|
|
1616
1690
|
const nonce = randomPermit2Nonce();
|
|
1617
|
-
const deadline = BigInt(
|
|
1691
|
+
const deadline = BigInt(
|
|
1692
|
+
Math.floor(Date.now() / 1e3) + PERMIT_WINDOW_SECONDS
|
|
1693
|
+
);
|
|
1618
1694
|
const typedData = buildPermitTransferFromTypedData({
|
|
1619
1695
|
chainId: cid,
|
|
1620
1696
|
message: {
|
|
@@ -1625,9 +1701,11 @@ function makeSponsoredWethCallback(deps) {
|
|
|
1625
1701
|
}
|
|
1626
1702
|
});
|
|
1627
1703
|
const wallet = deps.getWalletClient(cid);
|
|
1628
|
-
const signature = await wallet.signTypedData(
|
|
1629
|
-
|
|
1630
|
-
|
|
1704
|
+
const signature = await wallet.signTypedData({
|
|
1705
|
+
account: deps.ownerAddress,
|
|
1706
|
+
...typedData
|
|
1707
|
+
});
|
|
1708
|
+
deps.onApproved?.();
|
|
1631
1709
|
const result = await post({
|
|
1632
1710
|
baseUrl: deps.baseUrl,
|
|
1633
1711
|
apiKey: deps.apiKey,
|
|
@@ -1790,14 +1868,16 @@ var OwneySDK = class {
|
|
|
1790
1868
|
* provider with viem `custom(provider)` to read token meta and sign the
|
|
1791
1869
|
* `TransferWithAuthorization`, then POSTs to the sponsor API.
|
|
1792
1870
|
*/
|
|
1793
|
-
getDefaultSponsoredCallback() {
|
|
1794
|
-
if (
|
|
1871
|
+
getDefaultSponsoredCallback(onApproved) {
|
|
1872
|
+
if (!onApproved && this.cachedSponsoredCallback)
|
|
1873
|
+
return this.cachedSponsoredCallback;
|
|
1795
1874
|
const provider = this.requireConnectedProvider();
|
|
1796
1875
|
const owner = this.state.walletAddress;
|
|
1797
|
-
|
|
1876
|
+
const callback = makeSponsoredDepositCallback({
|
|
1798
1877
|
apiKey: this.apiKey,
|
|
1799
1878
|
baseUrl: this.routingApiBaseUrl,
|
|
1800
1879
|
ownerAddress: owner,
|
|
1880
|
+
onApproved,
|
|
1801
1881
|
tokenAddressByChain: SPONSORED_USDC_BY_CHAIN,
|
|
1802
1882
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1803
1883
|
// PublicClient/WalletClient param types — structurally identical at
|
|
@@ -1812,7 +1892,8 @@ var OwneySDK = class {
|
|
|
1812
1892
|
transport: custom(provider)
|
|
1813
1893
|
})
|
|
1814
1894
|
});
|
|
1815
|
-
|
|
1895
|
+
if (!onApproved) this.cachedSponsoredCallback = callback;
|
|
1896
|
+
return callback;
|
|
1816
1897
|
}
|
|
1817
1898
|
/**
|
|
1818
1899
|
* Lazily builds (and caches) the default Permit2 sponsored WETH deposit
|
|
@@ -1820,15 +1901,16 @@ var OwneySDK = class {
|
|
|
1820
1901
|
* deposit. Mirrors `getDefaultSponsoredCallback()` but signs a Permit2
|
|
1821
1902
|
* `PermitTransferFrom` instead of an EIP-3009 authorization.
|
|
1822
1903
|
*/
|
|
1823
|
-
getDefaultWethSponsoredCallback() {
|
|
1824
|
-
if (this.cachedWethSponsoredCallback)
|
|
1904
|
+
getDefaultWethSponsoredCallback(onApproved) {
|
|
1905
|
+
if (!onApproved && this.cachedWethSponsoredCallback)
|
|
1825
1906
|
return this.cachedWethSponsoredCallback;
|
|
1826
1907
|
const provider = this.requireConnectedProvider();
|
|
1827
1908
|
const owner = this.state.walletAddress;
|
|
1828
|
-
|
|
1909
|
+
const callback = makeSponsoredWethCallback({
|
|
1829
1910
|
apiKey: this.apiKey,
|
|
1830
1911
|
baseUrl: this.routingApiBaseUrl,
|
|
1831
1912
|
ownerAddress: owner,
|
|
1913
|
+
onApproved,
|
|
1832
1914
|
tokenAddressByChain: SPONSORED_WETH_BY_CHAIN,
|
|
1833
1915
|
// Casts work around viem's chain-narrowed Client vs the generic
|
|
1834
1916
|
// PublicClient/WalletClient param types — structurally identical at
|
|
@@ -1843,7 +1925,8 @@ var OwneySDK = class {
|
|
|
1843
1925
|
transport: custom(provider)
|
|
1844
1926
|
})
|
|
1845
1927
|
});
|
|
1846
|
-
|
|
1928
|
+
if (!onApproved) this.cachedWethSponsoredCallback = callback;
|
|
1929
|
+
return callback;
|
|
1847
1930
|
}
|
|
1848
1931
|
getAgent(agentId) {
|
|
1849
1932
|
const agent = this.agents.get(agentId);
|
|
@@ -1989,13 +2072,13 @@ var OwneySDK = class {
|
|
|
1989
2072
|
* @returns {OwneyDepositResult} for a single agent, or {OwneyMultiDepositResult} with per-agent results
|
|
1990
2073
|
*/
|
|
1991
2074
|
async deposit(options) {
|
|
1992
|
-
const { amount, asset, depositCallback, agentId } = options;
|
|
2075
|
+
const { amount, asset, depositCallback, agentId, onApproved } = options;
|
|
1993
2076
|
if (BigInt(amount) === 0n) {
|
|
1994
2077
|
return { agentResults: {} };
|
|
1995
2078
|
}
|
|
1996
2079
|
const state = this.requireState();
|
|
1997
2080
|
const chainId = this.requireChainId();
|
|
1998
|
-
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback() : this.getDefaultSponsoredCallback());
|
|
2081
|
+
const effectiveCallback = depositCallback ?? (asset === "WETH" ? this.getDefaultWethSponsoredCallback(onApproved) : this.getDefaultSponsoredCallback(onApproved));
|
|
1999
2082
|
if (agentId) {
|
|
2000
2083
|
if (this.isAgentDisabled(agentId)) {
|
|
2001
2084
|
throw new OwneyError(
|