diff --git a/.env.example b/.env.example
index d50f687c..87fb5bb1 100644
--- a/.env.example
+++ b/.env.example
@@ -16,4 +16,5 @@ NEXT_PUBLIC_REGTEST_DEVNET_ARES_URL=https://bitcoin-api-gateway-regtest-devnet.z
NEXT_PUBLIC_REGTEST_DEVNET_AEGLE_URL=https://api-regtest-devnet.apollobyzeus.space
+# TODO: You can customize the redeem address here
NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS=
diff --git a/.gitignore b/.gitignore
index 7728c84f..337f041c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,5 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
-# npm
-.npmrc
-
# dependencies
/node_modules
/.pnp
diff --git a/README.md b/README.md
index 36941dfb..6ec175b1 100644
--- a/README.md
+++ b/README.md
@@ -481,9 +481,9 @@ export default function Home() {
// although we have a array of hotReserveBuckets, but the user could only bind one bitcoin address with the protocol, so we only need to get the first one
const hotReserveBuckets =
- await zplClient.getHotReserveBucketsByBitcoinXOnlyPubkey(
- userXOnlyPublicKey
- );
+ await zplClient.twoWayPeg.accounts.getHotReserveBucketsByBitcoinXOnlyPubkey(
+ userXOnlyPublicKey
+ );
if (!hotReserveBuckets || hotReserveBuckets.length === 0) {
console.log("No hot reserve address found");
@@ -670,6 +670,12 @@ export default function Home() {
.toString()
);
+ const receiverAta = getAssociatedTokenAddressSync(
+ zplClient.assetMint,
+ solanaPubkey,
+ true
+ );
+
const ixs: TransactionInstruction[] = [];
let remainingAmount = redeemAmountBN.clone();
@@ -684,48 +690,53 @@ export default function Home() {
if (!twoWayPegGuardianSetting)
throw new Error("Two way peg guardian setting not found");
- const retrieveIx = zplClient.constructRetrieveIx(
- amountToRedeem,
- new PublicKey(twoWayPegGuardianSetting)
- );
-
- ixs.push(retrieveIx);
-
- const escrow_address = process.env.NEXT_PUBLIC_ESCROW_ADDRESS; // set your escrow address here or other method you like
- if(escrow_address) {
- const targetAddress = new PublicKey(escrow_address);
- const toATA = getAssociatedTokenAddressSync(
- new PublicKey(config.assetMint),
- targetAddress,
- true // allow off curve to approve PDA
- );
- // check if the associated token account of target address initialized
- const info = await connection.getAccountInfo(toATA);
- if (!info) {
- // if not, create one
- const createIx = createAssociatedTokenAccountInstruction(
- solanaPubkey,
- toATA,
- targetAddress,
- new PublicKey(config.assetMint)
- );
- ixs.push(createIx);
- }
- // add a transfer instruction to transfer the tokens to the receive_address
- const transferIx = createTransferInstruction(
- receiverAta,
- toATA,
+ const retrieveIx =
+ zplClient.liquidityManagement.instructions.buildRetrieveIx(
+ amountToRedeem,
solanaPubkey,
- BigInt(amountToRedeem.toString())
+ zplClient.assetMint,
+ new PublicKey(twoWayPegGuardianSetting),
+ receiverAta
);
- ixs.push(transferIx);
- }
+ ixs.push(retrieveIx);
remainingAmount = remainingAmount.sub(amountToRedeem);
if (remainingAmount.eq(new BN(0))) break;
}
+ // TODO: You can customize the retrieve address here
+ if (process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS) {
+ const targetAddress = new PublicKey(
+ process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS
+ );
+ const toATA = getAssociatedTokenAddressSync(
+ new PublicKey(config.assetMint),
+ targetAddress,
+ true
+ );
+ // check if the target address has an associated token account
+ const info = await connection.getAccountInfo(toATA);
+ if (!info) {
+ // if not, create one
+ const createIx = createAssociatedTokenAccountInstruction(
+ solanaPubkey,
+ toATA,
+ targetAddress,
+ new PublicKey(config.assetMint)
+ );
+ ixs.push(createIx);
+ }
+ // add a transfer instruction to transfer the tokens to the receive_address
+ const transferIx = createTransferInstruction(
+ receiverAta,
+ toATA,
+ solanaPubkey,
+ BigInt(redeemAmountBN.toString())
+ );
+ ixs.push(transferIx);
+ }
+
const sig = await zplClient.signAndSendTransactionWithInstructions(ixs);
console.log(sig);
} catch (error) {
@@ -824,13 +835,13 @@ export default function Home() {
);
const twoWayPegConfiguration =
- await zplClient.getTwoWayPegConfiguration();
+ await zplClient.twoWayPeg.accounts.getConfiguration();
const ixs: TransactionInstruction[] = [];
// NOTE: asset is in vault, so use the biggest position guardian first
if (assetFrom.isLocked) {
- if (!positions) {
+ if (!positions) {
return;
}
@@ -849,22 +860,36 @@ export default function Home() {
const twoWayPegGuardianSetting = twoWayPegGuardianSettings.find(
(setting) =>
- zplClient
- .deriveLiquidityManagementGuardianSettingAddress(
- new PublicKey(setting.address)
- )
- .toBase58() === position.guardianSetting.toBase58()
+ zplClient.liquidityManagement.pdas
+ .deriveVaultSettingAddress(new PublicKey(setting.address))
+ .toBase58() === position.vaultSetting.toBase58()
);
if (!twoWayPegGuardianSetting) return;
- const withdrawalRequestIx = zplClient.constructAddWithdrawalRequestIx(
- solanaPubkey,
- amountToWithdraw,
- convertP2trToTweakedXOnlyPubkey(selectedWallet),
- new PublicKey(twoWayPegGuardianSetting.address),
- twoWayPegConfiguration.layerFeeCollector
- );
+ const vaultSettingPda =
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
+ new PublicKey(twoWayPegGuardianSetting.address)
+ );
+
+ const currentTimestamp = new BN(Date.now() / 1000);
+
+ const withdrawalRequestIx =
+ zplClient.twoWayPeg.instructions.buildAddWithdrawalRequestIx(
+ amountToWithdraw,
+ currentTimestamp,
+ convertP2trToTweakedXOnlyPubkey(selectedWallet),
+ solanaPubkey,
+ twoWayPegConfiguration.layerFeeCollector,
+ new PublicKey(twoWayPegGuardianSetting.address),
+ zplClient.liquidityManagementProgramId,
+ zplClient.liquidityManagement.pdas.deriveConfigurationAddress(),
+ vaultSettingPda,
+ zplClient.liquidityManagement.pdas.derivePositionAddress(
+ vaultSettingPda,
+ solanaPubkey
+ )
+ );
ixs.push(withdrawalRequestIx);
remainingAmount = remainingAmount.sub(amountToWithdraw);
@@ -873,14 +898,14 @@ export default function Home() {
}
// NOTE: asset is in wallet, so need to check all guardians store quota and store to the biggest quota guardian first
} else {
- const twoWayPegGuardiansWithQuota = await Promise.all(
+ const twoWayPegGuardiansWithQuota = await Promise.all(
twoWayPegGuardianSettings.map(async (twoWayPegGuardianSetting) => {
const totalSplTokenMinted = new BN(
twoWayPegGuardianSetting.total_amount_pegged
);
const splTokenVaultAuthority =
- zplClient.deriveSplTokenVaultAuthorityAddress(
+ zplClient.liquidityManagement.pdas.deriveSplTokenVaultAuthorityAddress(
new PublicKey(twoWayPegGuardianSetting.address)
);
@@ -905,7 +930,7 @@ export default function Home() {
address: twoWayPegGuardianSetting.address,
remainingStoreQuota,
liquidityManagementGuardianSetting:
- zplClient.deriveLiquidityManagementGuardianSettingAddress(
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
new PublicKey(twoWayPegGuardianSetting.address)
),
};
@@ -924,18 +949,37 @@ export default function Home() {
remainingAmount
);
- const storeIx = zplClient.constructStoreIx(
- withdrawAmountBN,
- new PublicKey(twoWayPegGuardian.address)
- );
+ const storeIx =
+ zplClient.liquidityManagement.instructions.buildStoreIx(
+ withdrawAmountBN,
+ solanaPubkey,
+ zplClient.assetMint,
+ new PublicKey(twoWayPegGuardian.address)
+ );
- const withdrawalRequestIx = zplClient.constructAddWithdrawalRequestIx(
- solanaPubkey,
- amountToWithdraw,
- convertP2trToTweakedXOnlyPubkey(selectedWallet),
- new PublicKey(twoWayPegGuardian.address),
- twoWayPegConfiguration.layerFeeCollector
- );
+ const vaultSettingPda =
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
+ new PublicKey(twoWayPegGuardian.address)
+ );
+
+ const currentTimestamp = new BN(Date.now() / 1000);
+
+ const withdrawalRequestIx =
+ zplClient.twoWayPeg.instructions.buildAddWithdrawalRequestIx(
+ amountToWithdraw,
+ currentTimestamp,
+ convertP2trToTweakedXOnlyPubkey(selectedWallet),
+ solanaPubkey,
+ twoWayPegConfiguration.layerFeeCollector,
+ new PublicKey(twoWayPegGuardian.address),
+ zplClient.liquidityManagementProgramId,
+ zplClient.liquidityManagement.pdas.deriveConfigurationAddress(),
+ vaultSettingPda,
+ zplClient.liquidityManagement.pdas.derivePositionAddress(
+ vaultSettingPda,
+ solanaPubkey
+ )
+ );
ixs.push(storeIx);
ixs.push(withdrawalRequestIx);
diff --git a/cspell.json b/cspell.json
index f928b91a..aa000416 100644
--- a/cspell.json
+++ b/cspell.json
@@ -95,7 +95,8 @@
"Schnorr",
"nums",
"cobo",
- "Xonly"
+ "Xonly",
+ "pdas"
],
// flagWords - list of words to be always considered incorrect
// This is useful for offensive words and common spelling errors.
diff --git a/package-lock.json b/package-lock.json
index 2e66599c..151a01d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"dependencies": {
"@bitcoinerlab/secp256k1": "^1.1.1",
"@cloudflare/next-on-pages": "^1.13.10",
- "@coral-xyz/borsh": "^0.30.1",
+ "@coral-xyz/borsh": "^0.31.1",
"@mdx-js/loader": "^3.0.1",
"@mdx-js/react": "^3.0.1",
"@next/mdx": "^14.2.3",
@@ -19,20 +19,19 @@
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-tooltip": "^1.1.4",
"@sentry/nextjs": "^8.26.0",
- "@solana/buffer-layout": "^4.0.1",
- "@solana/spl-token": "^0.4.6",
+ "@solana/spl-token": "^0.4.13",
"@solana/wallet-adapter-base": "^0.9.23",
"@solana/wallet-adapter-react": "^0.15.35",
"@solana/wallet-adapter-react-ui": "^0.9.35",
"@solana/wallet-adapter-wallets": "^0.19.32",
- "@solana/web3.js": "^1.91.8",
+ "@solana/web3.js": "^1.98.2",
+ "@zeus-network/zpl-sdk": "^0.11.1",
"axios": "^1.7.2",
"bech32": "^2.0.0",
"bignumber.js": "^9.1.2",
"bip32": "^4.0.0",
"bip65": "^1.0.3",
"bitcoinjs-lib": "^6.1.5",
- "bs58": "^5.0.0",
"class-variance-authority": "^0.7.0",
"classnames": "^2.5.1",
"clsx": "^2.1.1",
@@ -43,7 +42,6 @@
"ecpair": "^2.1.0",
"framer-motion": "^11.1.7",
"fs": "^0.0.1-security",
- "js-sha256": "^0.11.0",
"lucide-react": "^0.456.0",
"motion": "^12.0.11",
"next": "^14.2.3",
@@ -60,7 +58,6 @@
"swr": "^2.2.5",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
- "uint8array-tools": "^0.0.9",
"usehooks-ts": "^3.1.0",
"zod": "^3.23.8",
"zustand": "^4.5.2"
@@ -72,7 +69,6 @@
"@next/eslint-plugin-next": "^14.2.3",
"@tailwindcss/typography": "^0.5.13",
"@types/bn.js": "^5.1.5",
- "@types/bs58": "^4.0.4",
"@types/d3": "^7.4.3",
"@types/mdx": "^2.0.13",
"@types/node": "^20",
@@ -96,6 +92,45 @@
"node": "20.18.3"
}
},
+ "../zpl-sdk-js": {
+ "name": "@zeus-network/zpl-sdk",
+ "version": "0.11.1",
+ "extraneous": true,
+ "license": "MIT",
+ "dependencies": {
+ "@bitcoinerlab/secp256k1": "^1.2.0",
+ "@coral-xyz/borsh": "^0.31.1",
+ "@solana/buffer-layout": "^4.0.1",
+ "bitcoinjs-lib": "^6.1.7",
+ "bn.js": "^5.2.2",
+ "bs58": "^5.0.0",
+ "js-sha256": "^0.11.0",
+ "uint8array-tools": "^0.0.9"
+ },
+ "devDependencies": {
+ "@commitlint/cli": "^19.8.0",
+ "@commitlint/config-conventional": "^19.8.0",
+ "@eslint/js": "^9.26.0",
+ "@types/bn.js": "^5.1.6",
+ "@types/bs58": "^4.0.4",
+ "@types/node": "^22.14.1",
+ "cspell": "^9.0.0",
+ "eslint": "^9.26.0",
+ "eslint-config-prettier": "^10.1.3",
+ "eslint-plugin-prettier": "^5.4.0",
+ "eslint-plugin-simple-import-sort": "^12.1.1",
+ "husky": "^9.1.7",
+ "lint-staged": "^15.5.2",
+ "prettier": "^3.5.3",
+ "rolldown": "1.0.0-beta.7",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.32.0"
+ },
+ "peerDependencies": {
+ "@solana/spl-token": "^0.4.13",
+ "@solana/web3.js": "^1.98.2"
+ }
+ },
"node_modules/@adraffy/ens-normalize": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz",
@@ -2698,9 +2733,9 @@
}
},
"node_modules/@coral-xyz/borsh": {
- "version": "0.30.1",
- "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.30.1.tgz",
- "integrity": "sha512-aaxswpPrCFKl8vZTbxLssA2RvwX2zmKLlRCIktJOwW+VpVwYtXRtlWiIP+c2pPRKneiTiWCN2GEMSH9j1zTlWQ==",
+ "version": "0.31.1",
+ "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.31.1.tgz",
+ "integrity": "sha512-9N8AU9F0ubriKfNE3g1WF0/4dtlGXoBN/hd1PvbNBamBNwRgHxH4P+o3Zt7rSEloW1HUs6LfZEchlx9fW7POYw==",
"license": "Apache-2.0",
"dependencies": {
"bn.js": "^5.1.2",
@@ -2710,7 +2745,7 @@
"node": ">=10"
},
"peerDependencies": {
- "@solana/web3.js": "^1.68.0"
+ "@solana/web3.js": "^1.69.0"
}
},
"node_modules/@cspell/cspell-bundled-dicts": {
@@ -12480,17 +12515,17 @@
}
},
"node_modules/@solana/web3.js": {
- "version": "1.98.0",
- "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.0.tgz",
- "integrity": "sha512-nz3Q5OeyGFpFCR+erX2f6JPt3sKhzhYcSycBCSPkWjzSVDh/Rr1FqTVMRe58FKO16/ivTUcuJjeS5MyBvpkbzA==",
+ "version": "1.98.2",
+ "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.98.2.tgz",
+ "integrity": "sha512-BqVwEG+TaG2yCkBMbD3C4hdpustR4FpuUFRPUmqRZYYlPI9Hg4XMWxHWOWRzHE9Lkc9NDjzXFX7lDXSgzC7R1A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.25.0",
"@noble/curves": "^1.4.2",
"@noble/hashes": "^1.4.0",
"@solana/buffer-layout": "^4.0.1",
+ "@solana/codecs-numbers": "^2.1.0",
"agentkeepalive": "^4.5.0",
- "bigint-buffer": "^1.1.5",
"bn.js": "^5.2.1",
"borsh": "^0.7.0",
"bs58": "^4.0.1",
@@ -12502,6 +12537,56 @@
"superstruct": "^2.0.2"
}
},
+ "node_modules/@solana/web3.js/node_modules/@solana/codecs-core": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-2.1.0.tgz",
+ "integrity": "sha512-SR7pKtmJBg2mhmkel2NeHA1pz06QeQXdMv8WJoIR9m8F/hw80K/612uaYbwTt2nkK0jg/Qn/rNSd7EcJ4SBGjw==",
+ "license": "MIT",
+ "dependencies": {
+ "@solana/errors": "2.1.0"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/@solana/codecs-numbers": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-2.1.0.tgz",
+ "integrity": "sha512-XMu4yw5iCgQnMKsxSWPPOrGgtaohmupN3eyAtYv3K3C/MJEc5V90h74k5B1GUCiHvcrdUDO9RclNjD9lgbjFag==",
+ "license": "MIT",
+ "dependencies": {
+ "@solana/codecs-core": "2.1.0",
+ "@solana/errors": "2.1.0"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5"
+ }
+ },
+ "node_modules/@solana/web3.js/node_modules/@solana/errors": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-2.1.0.tgz",
+ "integrity": "sha512-l+GxAv0Ar4d3c3PlZdA9G++wFYZREEbbRyAFP8+n8HSg0vudCuzogh/13io6hYuUhG/9Ve8ARZNamhV7UScKNw==",
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.3.0",
+ "commander": "^13.1.0"
+ },
+ "bin": {
+ "errors": "bin/cli.mjs"
+ },
+ "engines": {
+ "node": ">=20.18.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=5"
+ }
+ },
"node_modules/@solana/web3.js/node_modules/bs58": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz",
@@ -12511,6 +12596,15 @@
"base-x": "^3.0.2"
}
},
+ "node_modules/@solana/web3.js/node_modules/commander": {
+ "version": "13.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz",
+ "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@solflare-wallet/metamask-sdk": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@solflare-wallet/metamask-sdk/-/metamask-sdk-1.0.3.tgz",
@@ -13364,17 +13458,6 @@
"@types/node": "*"
}
},
- "node_modules/@types/bs58": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@types/bs58/-/bs58-4.0.4.tgz",
- "integrity": "sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "base-x": "^3.0.6"
- }
- },
"node_modules/@types/connect": {
"version": "3.4.36",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.36.tgz",
@@ -17050,6 +17133,26 @@
"license": "Apache-2.0",
"peer": true
},
+ "node_modules/@zeus-network/zpl-sdk": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/@zeus-network/zpl-sdk/-/zpl-sdk-0.11.1.tgz",
+ "integrity": "sha512-BIjEAiVOkFOa1QEU0AejG+Ra51mhDL1XicF8rVuKs9KKmfVmlY/+FTwyztF0QO8bMjkh/2uH4QKOtX3RjG+3Ag==",
+ "license": "MIT",
+ "dependencies": {
+ "@bitcoinerlab/secp256k1": "^1.2.0",
+ "@coral-xyz/borsh": "^0.31.1",
+ "@solana/buffer-layout": "^4.0.1",
+ "bitcoinjs-lib": "^6.1.7",
+ "bn.js": "^5.2.2",
+ "bs58": "^5.0.0",
+ "js-sha256": "^0.11.0",
+ "uint8array-tools": "^0.0.9"
+ },
+ "peerDependencies": {
+ "@solana/spl-token": "^0.4.13",
+ "@solana/web3.js": "^1.98.2"
+ }
+ },
"node_modules/abbrev": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.0.tgz",
@@ -18157,9 +18260,9 @@
"license": "MIT"
},
"node_modules/bn.js": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
- "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz",
+ "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==",
"license": "MIT"
},
"node_modules/body-scroll-lock": {
diff --git a/package.json b/package.json
index 85503858..502c15d2 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"dependencies": {
"@bitcoinerlab/secp256k1": "^1.1.1",
"@cloudflare/next-on-pages": "^1.13.10",
- "@coral-xyz/borsh": "^0.30.1",
+ "@coral-xyz/borsh": "^0.31.1",
"@mdx-js/loader": "^3.0.1",
"@mdx-js/react": "^3.0.1",
"@next/mdx": "^14.2.3",
@@ -38,20 +38,19 @@
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-tooltip": "^1.1.4",
"@sentry/nextjs": "^8.26.0",
- "@solana/buffer-layout": "^4.0.1",
- "@solana/spl-token": "^0.4.6",
+ "@solana/spl-token": "^0.4.13",
"@solana/wallet-adapter-base": "^0.9.23",
"@solana/wallet-adapter-react": "^0.15.35",
"@solana/wallet-adapter-react-ui": "^0.9.35",
"@solana/wallet-adapter-wallets": "^0.19.32",
- "@solana/web3.js": "^1.91.8",
+ "@solana/web3.js": "^1.98.2",
+ "@zeus-network/zpl-sdk": "^0.11.1",
"axios": "^1.7.2",
"bech32": "^2.0.0",
"bignumber.js": "^9.1.2",
"bip32": "^4.0.0",
"bip65": "^1.0.3",
"bitcoinjs-lib": "^6.1.5",
- "bs58": "^5.0.0",
"class-variance-authority": "^0.7.0",
"classnames": "^2.5.1",
"clsx": "^2.1.1",
@@ -62,7 +61,6 @@
"ecpair": "^2.1.0",
"framer-motion": "^11.1.7",
"fs": "^0.0.1-security",
- "js-sha256": "^0.11.0",
"lucide-react": "^0.456.0",
"motion": "^12.0.11",
"next": "^14.2.3",
@@ -79,7 +77,6 @@
"swr": "^2.2.5",
"tailwind-merge": "^2.5.4",
"tailwindcss-animate": "^1.0.7",
- "uint8array-tools": "^0.0.9",
"usehooks-ts": "^3.1.0",
"zod": "^3.23.8",
"zustand": "^4.5.2"
@@ -91,7 +88,6 @@
"@next/eslint-plugin-next": "^14.2.3",
"@tailwindcss/typography": "^0.5.13",
"@types/bn.js": "^5.1.5",
- "@types/bs58": "^4.0.4",
"@types/d3": "^7.4.3",
"@types/mdx": "^2.0.13",
"@types/node": "^20",
diff --git a/src/bitcoin/index.ts b/src/bitcoin/index.ts
index 88eb3e1e..d4a475a5 100644
--- a/src/bitcoin/index.ts
+++ b/src/bitcoin/index.ts
@@ -1,9 +1,6 @@
import * as bitcoin from "bitcoinjs-lib";
-import { toXOnly } from "bitcoinjs-lib/src/psbt/bip371";
import BN from "bn.js";
-import * as tools from "uint8array-tools";
-import { UTXO, UTXOs } from "@/types/api";
import { BitcoinNetwork } from "@/types/store";
import { BitcoinXOnlyPublicKey } from "@/types/wallet";
@@ -11,13 +8,6 @@ export const UNLOCK_BLOCK_HEIGHT = 4320; // 144 blocks (1 day) * 30
const SATOSHIS_PER_BTC = new BN(1e8);
-const TX_INPUT_VBYTE: number = 58;
-const TX_BASIC_VBYTE: number = 10;
-const TX_OUTPUT_VBYTE: number = 44;
-
-// FIXME: need to figure out the dust amount
-const DUST_AMOUNT: number = 546;
-
// FIXME: move to a more appropriate location
/**
* Converts BTC to Satoshis.
@@ -133,237 +123,4 @@ export const convertBitcoinNetwork = (bitcoinNetwork: BitcoinNetwork) => {
throw new Error("Invalid network type");
};
-const isSpendable = (utxo: UTXO, satoshisPerVBytes: number): boolean => {
- return (
- BigInt(Math.round(utxo.satoshis)) >
- BigInt(Math.ceil(satoshisPerVBytes * TX_INPUT_VBYTE))
- );
-};
-
-/**
- *
- * @param utxos available utxos
- * @param hotReserveAddress hot reserve address in p2tr format
- * @param amount amount to deposit (satoshis)
- * @param userXOnlyPubKey userXonlyPubKey
- * @param feeRate fee rate in satoshis per vbyte
- * @param network network
- * @returns
- */
-export const constructDepositToHotReserveTx = (
- utxos: UTXOs,
- hotReserveAddress: string,
- amount: number,
- userXOnlyPubKey: BitcoinXOnlyPublicKey,
- feeRate: number,
- network: bitcoin.networks.Network,
- isDepositAll: boolean = false
-): {
- psbt: bitcoin.Psbt;
- amountToSend: number;
- returnAmount: number;
- usedUTXOs: UTXOs;
-} => {
- if (utxos.length === 0) {
- throw new Error("No UTXOs available");
- }
-
- if (feeRate < 1) {
- throw new Error("Invalid satoshisPerVBytes");
- }
-
- // FIXME: sort utxos by satoshis from low to high
- utxos.sort((a, b) => a.satoshis - b.satoshis);
-
- // if the fee is higher than the amount to deposit
- const spendableUTXOs = utxos.filter((utxo) => isSpendable(utxo, feeRate));
-
- if (spendableUTXOs.length === 0) {
- throw new Error("No spendable UTXOs available");
- }
-
- // available amount
- const totalAvailableAmount = spendableUTXOs.reduce(
- (acc, utxo) => acc + utxo.satoshis,
- 0
- );
-
- if (totalAvailableAmount < amount) {
- throw new Error("Insufficient balance");
- }
-
- const amountToSend = amount;
-
- const { output, address } = bitcoin.payments.p2tr({
- internalPubkey: userXOnlyPubKey,
- network: network,
- });
-
- if (!output) {
- throw new Error("Invalid output");
- }
-
- if (!address) {
- throw new Error("Invalid address");
- }
-
- const psbt = new bitcoin.Psbt({ network }).setVersion(2);
-
- let TOTAL_VBYTE = TX_BASIC_VBYTE;
- let preparedAmount = BigInt(0);
-
- const pickedUTXOs: UTXOs = [];
-
- for (const utxo of spendableUTXOs) {
- psbt.addInput({
- hash: utxo.transaction_id,
- index: utxo.transaction_index,
- witnessUtxo: {
- script: output!,
- value: utxo.satoshis,
- },
- tapInternalKey: userXOnlyPubKey,
- });
- preparedAmount += BigInt(utxo.satoshis);
- TOTAL_VBYTE += TX_INPUT_VBYTE;
- pickedUTXOs.push(utxo);
- if (
- preparedAmount >=
- BigInt(amountToSend) + BigInt(feeRate) * BigInt(Math.ceil(TOTAL_VBYTE))
- ) {
- break;
- }
- }
-
- // basic 1 output
- TOTAL_VBYTE += TX_OUTPUT_VBYTE;
-
- // if not deposit all, add 1 more output
- if (!isDepositAll) {
- TOTAL_VBYTE += TX_OUTPUT_VBYTE;
- }
-
- const returnAmount = Number(
- preparedAmount -
- BigInt(amountToSend) -
- BigInt(feeRate) * BigInt(Math.ceil(TOTAL_VBYTE))
- );
-
- if (returnAmount < 0) {
- throw new Error("Insufficient balance for fee");
- }
-
- psbt.addOutput({
- address: hotReserveAddress,
- value: amountToSend,
- });
-
- // FIXME: there is a return amount, might need to handle minimum dust amount
- if (returnAmount != 0 && returnAmount > DUST_AMOUNT) {
- psbt.addOutput({
- address: address,
- value: returnAmount,
- });
- }
-
- psbt.setMaximumFeeRate(feeRate + 1);
-
- return {
- psbt,
- amountToSend: Number(amountToSend),
- returnAmount: Number(returnAmount),
- usedUTXOs: pickedUTXOs,
- };
-};
-
-/**
- *
- * @param utxos available utxos
- * @param feeRate fee rate in satoshis per vbyte
- * @returns spendable amount in satoshis
- */
-export const estimateMaxSpendableAmount = (
- utxos: UTXOs,
- feeRate: number
-): number => {
- if (utxos.length === 0) {
- return 0;
- }
-
- // FIXME: if need?
- const spendableUTXOs = utxos.filter((utxo) => isSpendable(utxo, feeRate));
-
- if (spendableUTXOs.length === 0) {
- return 0;
- }
-
- let preparedAmount = BigInt(0);
- let TOTAL_VBYTE = TX_BASIC_VBYTE;
-
- for (const utxo of spendableUTXOs) {
- TOTAL_VBYTE += TX_INPUT_VBYTE;
- preparedAmount += BigInt(utxo.satoshis);
- }
-
- // spend all means only 1 output
- TOTAL_VBYTE += TX_OUTPUT_VBYTE;
-
- const toSendAmount =
- preparedAmount - BigInt(feeRate) * BigInt(Math.ceil(TOTAL_VBYTE));
-
- return Number(toSendAmount);
-};
-
-/**
- * Calculate the hot reserve bucket address based on the cold reserve address's internal key and the user's unlocking script.
- * * the key_path_spend_public_key and script_path_spend_public_key must be tweaked public keys.
- * @param {Buffer} key_path_spend_public_key - cold reserve address's internal key (must be tweaked public key)
- * @param {Buffer} script_path_spend_public_key - user's unlocking script (must be tweaked public key)
- * @param {number} lockTime - the lock time of the hot reserve address
- * @param {bitcoin.Network=} network - the network to use
- * @return - the hot reserve address and the script
- */
-export function deriveHotReserveAddress(
- // tweaked pubkey that could directly spend the UTXO, usually the address of zeus node operator
- key_path_spend_public_key: Buffer,
- // user's unlocking script
- script_path_spend_public_key: Buffer,
- lockTime: number,
- network?: bitcoin.Network
-): {
- address: string;
- script: Buffer;
- hash: Buffer | undefined;
- output: Buffer | undefined;
- pubkey: Buffer | undefined;
-} {
- network = network ?? bitcoin.networks.regtest;
-
- // bitcoin csv encoding sample
- // * ref: https://github.com/bitcoinjs/bitcoinjs-lib/blob/151173f05e26a9af7c98d8d1e3f90e97185955f1/test/integration/csv.spec.ts#L61
- const targetScript = `${tools.toHex(bitcoin.script.number.encode(lockTime))} OP_CHECKSEQUENCEVERIFY OP_DROP ${toXOnly(script_path_spend_public_key).toString("hex")} OP_CHECKSIG`;
-
- const tap = bitcoin.script.fromASM(targetScript);
-
- const script_p2tr = bitcoin.payments.p2tr({
- internalPubkey: toXOnly(key_path_spend_public_key),
- scriptTree: {
- output: tap,
- },
- network,
- });
-
- if (script_p2tr.address === undefined) {
- throw new Error("Failed to calculate the address");
- }
-
- return {
- address: script_p2tr.address!,
- script: tap,
- hash: script_p2tr.hash,
- output: script_p2tr.output,
- pubkey: script_p2tr.pubkey,
- };
-}
-
export default bitcoin;
diff --git a/src/components/CryptoInput/Dropdown.tsx b/src/components/CryptoInput/Dropdown.tsx
index 91dd5ff6..b88f53ef 100644
--- a/src/components/CryptoInput/Dropdown.tsx
+++ b/src/components/CryptoInput/Dropdown.tsx
@@ -36,7 +36,6 @@ export default function InputDropdown({
>
{dropdownOptions.map((option) => {
- console.log(option);
return (
Promise
;
updateTransactions: () => Promise;
resetProvideAmountValue: () => void;
@@ -75,7 +74,6 @@ export default function ConfirmDepositModal({
minerFee,
assetFrom,
assetTo,
- isDepositAll,
signPsbt,
updateTransactions,
resetProvideAmountValue,
@@ -110,7 +108,7 @@ export default function ConfirmDepositModal({
// although we have a array of hotReserveBuckets, but the user could only bind one bitcoin address with the protocol, so we only need to get the first one
const hotReserveBuckets =
- await zplClient.getHotReserveBucketsByBitcoinXOnlyPubkey(
+ await zplClient.twoWayPeg.accounts.getHotReserveBucketsByBitcoinXOnlyPubkey(
userXOnlyPublicKey
);
@@ -122,7 +120,7 @@ export default function ConfirmDepositModal({
// NOTE: Regtest and Testnet use the same ZPL with different guardian settings, so we need to set guardian setting in env
const targetHotReserveBucket = hotReserveBuckets.find(
(bucket) =>
- bucket.guardianSetting.toBase58() === networkConfig.guardianSetting
+ bucket.reserveSetting.toBase58() === networkConfig.guardianSetting
);
if (!targetHotReserveBucket) throw new Error("Wrong guardian setting");
@@ -139,14 +137,13 @@ export default function ConfirmDepositModal({
let depositPsbt;
let usedBitcoinUTXOs;
try {
- const { psbt, usedUTXOs } = constructDepositToHotReserveTx(
+ const { psbt, usedUTXOs } = buildDepositToHotReserveTx(
bitcoinUTXOs,
targetHotReserveAddress,
btcToSatoshi(depositAmount),
userXOnlyPublicKey,
feeRate,
- convertBitcoinNetwork(bitcoinNetwork),
- isDepositAll
+ convertBitcoinNetwork(bitcoinNetwork)
);
depositPsbt = psbt;
usedBitcoinUTXOs = usedUTXOs;
@@ -172,7 +169,7 @@ export default function ConfirmDepositModal({
const transaction: Interaction = {
status: InteractionStatus.BitcoinDepositToHotReserve,
- interaction_id: zplClient
+ interaction_id: zplClient.twoWayPeg.pdas
.deriveInteraction(Buffer.from(txId, "hex"), new BN(0))
.toBase58(),
interaction_type: InteractionType.Deposit,
diff --git a/src/components/Mint/Modals/ConfirmWithdraw.tsx b/src/components/Mint/Modals/ConfirmWithdraw.tsx
index f3c6b366..7898b2ce 100644
--- a/src/components/Mint/Modals/ConfirmWithdraw.tsx
+++ b/src/components/Mint/Modals/ConfirmWithdraw.tsx
@@ -3,6 +3,7 @@ import { getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token";
import { WalletSignTransactionError } from "@solana/wallet-adapter-base";
import { useConnection } from "@solana/wallet-adapter-react";
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
+import { Position } from "@zeus-network/zpl-sdk/liquidity-management/types";
import BigNumber from "bignumber.js";
import { BN } from "bn.js";
import classNames from "classnames";
@@ -25,7 +26,6 @@ import { useZplClient } from "@/contexts/ZplClientProvider";
import useTwoWayPegGuardianSettings from "@/hooks/hermes/useTwoWayPegGuardianSettings";
import { InteractionType } from "@/types/api";
import { Chain } from "@/types/network";
-import { Position } from "@/types/zplClient";
import { BTC_DECIMALS } from "@/utils/constant";
import { shortenString } from "@/utils/format";
import { notifyError, notifyTx } from "@/utils/notification";
@@ -94,7 +94,7 @@ export default function ConfirmWithdraw({
);
const twoWayPegConfiguration =
- await zplClient.getTwoWayPegConfiguration();
+ await zplClient.twoWayPeg.accounts.getConfiguration();
const ixs: TransactionInstruction[] = [];
@@ -119,22 +119,36 @@ export default function ConfirmWithdraw({
const twoWayPegGuardianSetting = twoWayPegGuardianSettings.find(
(setting) =>
- zplClient
- .deriveLiquidityManagementGuardianSettingAddress(
- new PublicKey(setting.address)
- )
- .toBase58() === position.guardianSetting.toBase58()
+ zplClient.liquidityManagement.pdas
+ .deriveVaultSettingAddress(new PublicKey(setting.address))
+ .toBase58() === position.vaultSetting.toBase58()
);
if (!twoWayPegGuardianSetting) return;
- const withdrawalRequestIx = zplClient.constructAddWithdrawalRequestIx(
- solanaPubkey,
- amountToWithdraw,
- convertP2trToTweakedXOnlyPubkey(selectedWallet),
- new PublicKey(twoWayPegGuardianSetting.address),
- twoWayPegConfiguration.layerFeeCollector
- );
+ const vaultSettingPda =
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
+ new PublicKey(twoWayPegGuardianSetting.address)
+ );
+
+ const currentTimestamp = new BN(Date.now() / 1000);
+
+ const withdrawalRequestIx =
+ zplClient.twoWayPeg.instructions.buildAddWithdrawalRequestIx(
+ amountToWithdraw,
+ currentTimestamp,
+ convertP2trToTweakedXOnlyPubkey(selectedWallet),
+ solanaPubkey,
+ twoWayPegConfiguration.layerFeeCollector,
+ new PublicKey(twoWayPegGuardianSetting.address),
+ zplClient.liquidityManagementProgramId,
+ zplClient.liquidityManagement.pdas.deriveConfigurationAddress(),
+ vaultSettingPda,
+ zplClient.liquidityManagement.pdas.derivePositionAddress(
+ vaultSettingPda,
+ solanaPubkey
+ )
+ );
ixs.push(withdrawalRequestIx);
remainingAmount = remainingAmount.sub(amountToWithdraw);
@@ -150,7 +164,7 @@ export default function ConfirmWithdraw({
);
const splTokenVaultAuthority =
- zplClient.deriveSplTokenVaultAuthorityAddress(
+ zplClient.liquidityManagement.pdas.deriveSplTokenVaultAuthorityAddress(
new PublicKey(twoWayPegGuardianSetting.address)
);
@@ -175,7 +189,7 @@ export default function ConfirmWithdraw({
address: twoWayPegGuardianSetting.address,
remainingStoreQuota,
liquidityManagementGuardianSetting:
- zplClient.deriveLiquidityManagementGuardianSettingAddress(
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
new PublicKey(twoWayPegGuardianSetting.address)
),
};
@@ -194,18 +208,37 @@ export default function ConfirmWithdraw({
remainingAmount
);
- const storeIx = zplClient.constructStoreIx(
- withdrawAmountBN,
- new PublicKey(twoWayPegGuardian.address)
- );
+ const storeIx =
+ zplClient.liquidityManagement.instructions.buildStoreIx(
+ withdrawAmountBN,
+ solanaPubkey,
+ zplClient.assetMint,
+ new PublicKey(twoWayPegGuardian.address)
+ );
- const withdrawalRequestIx = zplClient.constructAddWithdrawalRequestIx(
- solanaPubkey,
- amountToWithdraw,
- convertP2trToTweakedXOnlyPubkey(selectedWallet),
- new PublicKey(twoWayPegGuardian.address),
- twoWayPegConfiguration.layerFeeCollector
- );
+ const vaultSettingPda =
+ zplClient.liquidityManagement.pdas.deriveVaultSettingAddress(
+ new PublicKey(twoWayPegGuardian.address)
+ );
+
+ const currentTimestamp = new BN(Date.now() / 1000);
+
+ const withdrawalRequestIx =
+ zplClient.twoWayPeg.instructions.buildAddWithdrawalRequestIx(
+ amountToWithdraw,
+ currentTimestamp,
+ convertP2trToTweakedXOnlyPubkey(selectedWallet),
+ solanaPubkey,
+ twoWayPegConfiguration.layerFeeCollector,
+ new PublicKey(twoWayPegGuardian.address),
+ zplClient.liquidityManagementProgramId,
+ zplClient.liquidityManagement.pdas.deriveConfigurationAddress(),
+ vaultSettingPda,
+ zplClient.liquidityManagement.pdas.derivePositionAddress(
+ vaultSettingPda,
+ solanaPubkey
+ )
+ );
ixs.push(storeIx);
ixs.push(withdrawalRequestIx);
@@ -221,7 +254,6 @@ export default function ConfirmWithdraw({
return sig;
};
- setIsWithdrawing(true);
action()
.catch((e) => {
if (e instanceof WalletSignTransactionError) {
diff --git a/src/components/MobileMenu/MobileMenuButton.tsx b/src/components/MobileMenu/MobileMenuButton.tsx
index 7a57cf0d..fde99e33 100644
--- a/src/components/MobileMenu/MobileMenuButton.tsx
+++ b/src/components/MobileMenu/MobileMenuButton.tsx
@@ -13,7 +13,6 @@ export default function MobileMenuButton() {
{
- console.log(currentModal);
if (currentModal === MODAL_NAMES.MOBILE_MENU) {
closeModal();
} else {
diff --git a/src/components/PortfolioV2/Modals/Redeem.tsx b/src/components/PortfolioV2/Modals/Redeem.tsx
index 4f37fb19..952c5915 100644
--- a/src/components/PortfolioV2/Modals/Redeem.tsx
+++ b/src/components/PortfolioV2/Modals/Redeem.tsx
@@ -7,6 +7,7 @@ import {
import { WalletSignTransactionError } from "@solana/wallet-adapter-base";
import { useWallet, useConnection } from "@solana/wallet-adapter-react";
import { PublicKey, TransactionInstruction } from "@solana/web3.js";
+import { Position } from "@zeus-network/zpl-sdk/liquidity-management/types";
import BigNumber from "bignumber.js";
import { BN } from "bn.js";
import { useState } from "react";
@@ -22,7 +23,6 @@ import { useNetworkConfig } from "@/hooks/misc/useNetworkConfig";
import usePositions from "@/hooks/zpl/usePositions";
import usePersistentStore from "@/stores/persistentStore";
import { Chain } from "@/types/network";
-import { Position } from "@/types/zplClient";
import { BTC_DECIMALS } from "@/utils/constant";
import { formatValue } from "@/utils/format";
import { notifyError, notifyTx } from "@/utils/notification";
@@ -134,6 +134,12 @@ export default function RedeemModal({
.toString()
);
+ const receiverAta = getAssociatedTokenAddressSync(
+ zplClient.assetMint,
+ solanaPubkey,
+ true
+ );
+
const ixs: TransactionInstruction[] = [];
let remainingAmount = redeemAmountBN.clone();
@@ -148,56 +154,53 @@ export default function RedeemModal({
if (!twoWayPegGuardianSetting)
throw new Error("Two way peg guardian setting not found");
- const receiverAta = getAssociatedTokenAddressSync(
- new PublicKey(config.assetMint),
- solanaPubkey,
- true
- );
-
- const retrieveIx = zplClient.constructRetrieveIx(
- amountToRedeem,
- new PublicKey(twoWayPegGuardianSetting),
- receiverAta
- );
- ixs.push(retrieveIx);
-
- // TODO: You can customize the retrieve address here
- if (process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS) {
- const targetAddress = new PublicKey(
- process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS
- );
- const toATA = getAssociatedTokenAddressSync(
- new PublicKey(config.assetMint),
- targetAddress,
- true
- );
- // check if the target address has an associated token account
- const info = await connection.getAccountInfo(toATA);
- if (!info) {
- // if not, create one
- const createIx = createAssociatedTokenAccountInstruction(
- solanaPubkey,
- toATA,
- targetAddress,
- new PublicKey(config.assetMint)
- );
- ixs.push(createIx);
- }
- // add a transfer instruction to transfer the tokens to the receive_address
- const transferIx = createTransferInstruction(
- receiverAta,
- toATA,
+ const retrieveIx =
+ zplClient.liquidityManagement.instructions.buildRetrieveIx(
+ amountToRedeem,
solanaPubkey,
- BigInt(amountToRedeem.toString())
+ zplClient.assetMint,
+ new PublicKey(twoWayPegGuardianSetting),
+ receiverAta
);
- ixs.push(transferIx);
- }
+ ixs.push(retrieveIx);
remainingAmount = remainingAmount.sub(amountToRedeem);
if (remainingAmount.eq(new BN(0))) break;
}
+ // TODO: You can customize the retrieve address here
+ if (process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS) {
+ const targetAddress = new PublicKey(
+ process.env.NEXT_PUBLIC_DEVNET_REDEEM_ADDRESS
+ );
+ const toATA = getAssociatedTokenAddressSync(
+ new PublicKey(config.assetMint),
+ targetAddress,
+ true
+ );
+ // check if the target address has an associated token account
+ const info = await connection.getAccountInfo(toATA);
+ if (!info) {
+ // if not, create one
+ const createIx = createAssociatedTokenAccountInstruction(
+ solanaPubkey,
+ toATA,
+ targetAddress,
+ new PublicKey(config.assetMint)
+ );
+ ixs.push(createIx);
+ }
+ // add a transfer instruction to transfer the tokens to the receive_address
+ const transferIx = createTransferInstruction(
+ receiverAta,
+ toATA,
+ solanaPubkey,
+ BigInt(redeemAmountBN.toString())
+ );
+ ixs.push(transferIx);
+ }
+
const sig = await zplClient.signAndSendTransactionWithInstructions(ixs);
await mutateBalance();
diff --git a/src/components/PortfolioV2/Overview/PortfolioDetails.tsx b/src/components/PortfolioV2/Overview/PortfolioDetails.tsx
index ed7c6119..ee099465 100644
--- a/src/components/PortfolioV2/Overview/PortfolioDetails.tsx
+++ b/src/components/PortfolioV2/Overview/PortfolioDetails.tsx
@@ -1,9 +1,9 @@
+import { Position } from "@zeus-network/zpl-sdk/liquidity-management/types";
import BigNumber from "bignumber.js";
import { useRef, useState } from "react";
import Button from "@/components/Button/Button";
import Icon from "@/components/Icons";
-import { Position } from "@/types/zplClient";
import { BTC_DECIMALS } from "@/utils/constant";
import { formatValue } from "@/utils/format";
diff --git a/src/components/PortfolioV2/Transactions/PortfolioTransactionsDeposits.tsx b/src/components/PortfolioV2/Transactions/PortfolioTransactionsDeposits.tsx
index d33b08b3..f06ff74b 100644
--- a/src/components/PortfolioV2/Transactions/PortfolioTransactionsDeposits.tsx
+++ b/src/components/PortfolioV2/Transactions/PortfolioTransactionsDeposits.tsx
@@ -79,7 +79,7 @@ const PortfolioTransactionsDeposits = ({
`/api/v1/raw/layer/interactions/${transaction.interaction_id}/steps`,
interactionSchema
);
- console.log("interactionDetail", interactionDetail);
+
setSelectedTransaction(interactionDetail);
let depositToHotReserveTxConfirmations = 0;
diff --git a/src/components/Widgets/MintWidget/Deposit.tsx b/src/components/Widgets/MintWidget/Deposit.tsx
index f440b301..d9d88903 100644
--- a/src/components/Widgets/MintWidget/Deposit.tsx
+++ b/src/components/Widgets/MintWidget/Deposit.tsx
@@ -1,9 +1,9 @@
import { PublicKey } from "@solana/web3.js";
+import { estimateMaxSpendableAmount } from "@zeus-network/zpl-sdk/bitcoin";
import { Psbt } from "bitcoinjs-lib";
import { useState } from "react";
-import { btcToSatoshi, satoshiToBtc } from "@/bitcoin";
-import { estimateMaxSpendableAmount } from "@/bitcoin";
+import { satoshiToBtc } from "@/bitcoin";
import Icon from "@/components/Icons";
import { DepositTooltip } from "@/components/Mint/DepositTooltip/DepositTooltip";
import AccountProcess from "@/components/Mint/Modals/AccountProcess";
@@ -270,7 +270,6 @@ export default function Deposit({
name: "zBTC",
isLocked: true,
}}
- isDepositAll={btcToSatoshi(provideAmount) === maxSpendableSatoshis}
signPsbt={signPsbt}
updateTransactions={updateDepositTransactions}
resetProvideAmountValue={resetProvideAmountValue}
diff --git a/src/components/Widgets/MintWidget/Withdraw.tsx b/src/components/Widgets/MintWidget/Withdraw.tsx
index 7d0ea2f9..61f40034 100644
--- a/src/components/Widgets/MintWidget/Withdraw.tsx
+++ b/src/components/Widgets/MintWidget/Withdraw.tsx
@@ -1,4 +1,5 @@
import { PublicKey } from "@solana/web3.js";
+import { Position } from "@zeus-network/zpl-sdk/liquidity-management/types";
import BigNumber from "bignumber.js";
import { useState } from "react";
@@ -12,7 +13,6 @@ import useTwoWayPegConfiguration from "@/hooks/zpl/useTwoWayPegConfiguration";
import usePersistentStore from "@/stores/persistentStore";
import useStore from "@/stores/store";
import { CryptoInputOption } from "@/types/misc";
-import { Position } from "@/types/zplClient";
import {
DEFAULT_SERVICE_FEE_BASIS_POINT_PERCENT,
BTC_DECIMALS,
diff --git a/src/hooks/zpl/useColdReserveBuckets.ts b/src/hooks/zpl/useColdReserveBuckets.ts
index 876df282..dce357a1 100644
--- a/src/hooks/zpl/useColdReserveBuckets.ts
+++ b/src/hooks/zpl/useColdReserveBuckets.ts
@@ -6,7 +6,7 @@ function useColdReserveBuckets() {
const client = useZplClient();
const { data, mutate, isLoading } = useSWR(
client ? [client, "getColdReserveBuckets"] : null,
- ([client]) => client.getColdReserveBuckets(),
+ ([client]) => client.twoWayPeg.accounts.getColdReserveBuckets(),
{
dedupingInterval: 3600000,
}
diff --git a/src/hooks/zpl/useHotReserveBucketActions.ts b/src/hooks/zpl/useHotReserveBucketActions.ts
index 9dd993ce..2c09a14c 100644
--- a/src/hooks/zpl/useHotReserveBucketActions.ts
+++ b/src/hooks/zpl/useHotReserveBucketActions.ts
@@ -1,9 +1,10 @@
import { useWallet } from "@solana/wallet-adapter-react";
import { PublicKey } from "@solana/web3.js";
+import { deriveHotReserveAddress } from "@zeus-network/zpl-sdk/bitcoin";
+import { HotReserveBucketStatus } from "@zeus-network/zpl-sdk/two-way-peg/types";
import { useCallback } from "react";
import { convertBitcoinNetwork, UNLOCK_BLOCK_HEIGHT } from "@/bitcoin";
-import { deriveHotReserveAddress } from "@/bitcoin";
import { getInternalXOnlyPubkeyFromUserWallet } from "@/bitcoin/wallet";
import { useZplClient } from "@/contexts/ZplClientProvider";
import { useNetworkConfig } from "@/hooks/misc/useNetworkConfig";
@@ -11,8 +12,8 @@ import usePersistentStore from "@/stores/persistentStore";
import { CheckBucketResult } from "@/types/misc";
import { Chain } from "@/types/network";
import { BitcoinWallet } from "@/types/wallet";
-import { HotReserveBucketStatus } from "@/types/zplClient";
import { createAxiosInstances } from "@/utils/axios";
+import { HOT_RESERVE_BUCKET_VALIDITY_PERIOD } from "@/utils/constant";
import { notifyTx } from "@/utils/notification";
import useTwoWayPegGuardianSettings from "../hermes/useTwoWayPegGuardianSettings";
@@ -35,7 +36,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
const selectedGuardian = twoWayPegGuardianSettings[0];
const coldReserveBucket = coldReserveBuckets.find(
- (bucket) => bucket.guardianSetting.toBase58() === selectedGuardian.address
+ (bucket) => bucket.reserveSetting.toBase58() === selectedGuardian.address
);
if (!coldReserveBucket)
@@ -61,18 +62,21 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
if (!hotReserveBitcoinXOnlyPublicKey)
throw new Error("Can't get hot reserve x-only publickey");
- const twoWayPegConfiguration = await zplClient.getTwoWayPegConfiguration();
+ const twoWayPegConfiguration =
+ await zplClient.twoWayPeg.accounts.getConfiguration();
- const ix = zplClient.constructCreateHotReserveBucketIx(
+ const ix = zplClient.twoWayPeg.instructions.buildCreateHotReserveBucketIx(
+ UNLOCK_BLOCK_HEIGHT,
+ HOT_RESERVE_BUCKET_VALIDITY_PERIOD,
solanaPubkey,
- hotReserveBitcoinXOnlyPublicKey,
userBitcoinXOnlyPublicKey,
- UNLOCK_BLOCK_HEIGHT,
+ hotReserveBitcoinXOnlyPublicKey,
new PublicKey(selectedGuardian.address),
new PublicKey(selectedGuardian.guardian_certificate),
coldReserveBucket.publicKey,
twoWayPegConfiguration.layerFeeCollector
);
+
const sig = await zplClient.signAndSendTransactionWithInstructions([ix]);
notifyTx(true, {
@@ -88,7 +92,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
`/api/v1/cobo-address`,
{
type: "hotReserveBucket",
- hotReserveBucketPda: zplClient
+ hotReserveBucketPda: zplClient.twoWayPeg.pdas
.deriveHotReserveBucketAddress(hotReserveBitcoinXOnlyPublicKey)
.toBase58(),
coldReserveBucketPda: coldReserveBucket.publicKey.toBase58(),
@@ -111,7 +115,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
]);
const reactivateHotReserveBucket = useCallback(async () => {
- if (!zplClient) return;
+ if (!zplClient || !solanaPubkey) return;
const userBitcoinXOnlyPublicKey =
getInternalXOnlyPubkeyFromUserWallet(bitcoinWallet);
@@ -119,7 +123,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
if (!userBitcoinXOnlyPublicKey) return;
const hotReserveBuckets =
- await zplClient.getHotReserveBucketsByBitcoinXOnlyPubkey(
+ await zplClient.twoWayPeg.accounts.getHotReserveBucketsByBitcoinXOnlyPubkey(
userBitcoinXOnlyPublicKey
);
@@ -127,16 +131,20 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
const targetHotReserveBucket = hotReserveBuckets.find(
(bucket) =>
- bucket.guardianSetting.toBase58() === networkConfig.guardianSetting
+ bucket.reserveSetting.toBase58() === networkConfig.guardianSetting
);
if (!targetHotReserveBucket) throw new Error("Wrong guardian setting");
- const twoWayPegConfiguration = await zplClient.getTwoWayPegConfiguration();
+ const twoWayPegConfiguration =
+ await zplClient.twoWayPeg.accounts.getConfiguration();
- const ix = zplClient.constructReactivateHotReserveBucketIx(
- targetHotReserveBucket.publicKey,
- twoWayPegConfiguration.layerFeeCollector
- );
+ const ix =
+ zplClient.twoWayPeg.instructions.buildReactivateHotReserveBucketIx(
+ HOT_RESERVE_BUCKET_VALIDITY_PERIOD,
+ solanaPubkey,
+ targetHotReserveBucket.publicKey,
+ twoWayPegConfiguration.layerFeeCollector
+ );
const sig = await zplClient.signAndSendTransactionWithInstructions([ix]);
notifyTx(true, {
@@ -144,7 +152,13 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
txId: sig,
solanaNetwork: solanaNetwork,
});
- }, [zplClient, bitcoinWallet, solanaNetwork, networkConfig.guardianSetting]);
+ }, [
+ zplClient,
+ solanaPubkey,
+ bitcoinWallet,
+ solanaNetwork,
+ networkConfig.guardianSetting,
+ ]);
const checkHotReserveBucketStatus = useCallback(async () => {
if (!zplClient || !solanaPubkey) return;
@@ -155,7 +169,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
if (!userBitcoinXOnlyPublicKey) return;
const hotReserveBuckets =
- await zplClient.getHotReserveBucketsByBitcoinXOnlyPubkey(
+ await zplClient.twoWayPeg.accounts.getHotReserveBucketsByBitcoinXOnlyPubkey(
userBitcoinXOnlyPublicKey
);
@@ -165,7 +179,7 @@ const useHotReserveBucketActions = (bitcoinWallet: BitcoinWallet | null) => {
// NOTE: Regtest and Testnet use the same ZPL with different guardian settings, so we need to set guardian setting in env, and our mechanism only create 1 hot reserve bucket for each bitcoin public key in mainnet.
const targetHotReserveBucket = hotReserveBuckets.find(
(bucket) =>
- bucket.guardianSetting.toBase58() === networkConfig.guardianSetting
+ bucket.reserveSetting.toBase58() === networkConfig.guardianSetting
);
if (!targetHotReserveBucket) throw new Error("Wrong guardian setting");
diff --git a/src/hooks/zpl/useHotReserveBucketsByOwner.ts b/src/hooks/zpl/useHotReserveBucketsByOwner.ts
index d7dfae9f..e3ebe0f8 100644
--- a/src/hooks/zpl/useHotReserveBucketsByOwner.ts
+++ b/src/hooks/zpl/useHotReserveBucketsByOwner.ts
@@ -10,7 +10,9 @@ function useHotReserveBucketsByOwner(solanaPubkey: PublicKey | null) {
? [client, solanaPubkey, "getHotReserveBucketsByOwner"]
: null,
([client, solanaPubkey]) =>
- client.getHotReserveBucketsBySolanaPubkey(solanaPubkey),
+ client.twoWayPeg.accounts.getHotReserveBucketsBySolanaPubkey(
+ solanaPubkey
+ ),
{
refreshInterval: 60000,
dedupingInterval: 60000,
diff --git a/src/hooks/zpl/usePositions.ts b/src/hooks/zpl/usePositions.ts
index 7bda23f0..07ffb462 100644
--- a/src/hooks/zpl/usePositions.ts
+++ b/src/hooks/zpl/usePositions.ts
@@ -12,15 +12,16 @@ function usePositions(solanaPubkey: PublicKey | null) {
? [client, solanaPubkey, "getPositionsByWallet"]
: null,
async ([client, solanaPubkey]) => {
- const positions = await client?.getPositionsByWallet(solanaPubkey);
+ const positions =
+ await client?.liquidityManagement.accounts.getPositionsByWallet(
+ solanaPubkey
+ );
const targetPositions = positions.filter(
(position) =>
- position.guardianSetting.toBase58() ===
- client
- .deriveLiquidityManagementGuardianSettingAddress(
- new PublicKey(config.guardianSetting)
- )
+ position.vaultSetting.toBase58() ===
+ client.liquidityManagement.pdas
+ .deriveVaultSettingAddress(new PublicKey(config.guardianSetting))
.toBase58()
);
diff --git a/src/hooks/zpl/useTwoWayPegConfiguration.ts b/src/hooks/zpl/useTwoWayPegConfiguration.ts
index b88aa073..f3608f1d 100644
--- a/src/hooks/zpl/useTwoWayPegConfiguration.ts
+++ b/src/hooks/zpl/useTwoWayPegConfiguration.ts
@@ -6,7 +6,7 @@ function useTwoWayPegConfiguration() {
const client = useZplClient();
const { data, mutate } = useSWR(
client ? [client, "getTwoWayPegConfiguration"] : null,
- () => client?.getTwoWayPegConfiguration(),
+ () => client?.twoWayPeg.accounts.getConfiguration(),
{
dedupingInterval: 600000,
}
diff --git a/src/types/zplClient.ts b/src/types/zplClient.ts
deleted file mode 100644
index 25d9a1c9..00000000
--- a/src/types/zplClient.ts
+++ /dev/null
@@ -1,189 +0,0 @@
-import * as borsh from "@coral-xyz/borsh";
-import { Structure } from "@solana/buffer-layout";
-import { PublicKey } from "@solana/web3.js";
-import BN from "bn.js";
-
-// Account Schema for Deserialization
-export interface TwoWayPegConfiguration {
- publicKey: PublicKey;
- superOperatorCertificate: PublicKey;
- zeusColdReserveRecoveryPublicKey: Uint8Array;
- zeusColdReserveRecoveryLockTime: number;
- layerFeeCollector: PublicKey;
- chadbufferAuthority: PublicKey;
- cpiIdentity: PublicKey;
- layerCaProgramId: PublicKey;
- bitcoinSpvProgramId: PublicKey;
- liquidityManagementProgramId: PublicKey;
- bucketOpenFeeAmount: BN;
- bucketReactivationFeeAmount: BN;
- withdrawalFeeAmount: BN;
- minerFeeRate: number;
-}
-
-export const twoWayPegConfigurationSchema: Structure
=
- borsh.struct([
- borsh.publicKey("superOperatorCertificate"),
- borsh.array(borsh.u8(), 32, "zeusColdReserveRecoveryPublicKey"),
- borsh.u16("zeusColdReserveRecoveryLockTime"),
- borsh.publicKey("layerFeeCollector"),
- borsh.publicKey("chadbufferAuthority"),
- borsh.publicKey("cpiIdentity"),
- borsh.publicKey("layerCaProgramId"),
- borsh.publicKey("bitcoinSpvProgramId"),
- borsh.publicKey("liquidityManagementProgramId"),
- borsh.u64("bucketOpenFeeAmount"),
- borsh.u64("bucketReactivationFeeAmount"),
- borsh.u64("withdrawalFeeAmount"),
- borsh.u32("minerFeeRate"),
- ]);
-
-export interface ColdReserveBucket {
- publicKey: PublicKey;
- guardianSetting: PublicKey;
- owner: PublicKey;
- // Bitcoin Cold Reserve X-Only Public Key
- taprootXOnlyPublicKey: Uint8Array;
- tapTweakHash: Uint8Array;
- createdAt: BN;
- // Guardian X-Only PublicKey
- keyPathSpendPublicKey: Uint8Array;
- recoveryParameters: ColdReserveRecoveryParameter[];
-}
-
-export interface ColdReserveRecoveryParameter {
- scriptPathSpendPublicKey: Uint8Array;
- lockTime: BN;
-}
-
-export const coldReserveBucketSchema: Structure =
- borsh.struct([
- borsh.publicKey("guardianSetting"),
- borsh.publicKey("owner"),
- borsh.array(borsh.u8(), 32, "taprootXOnlyPublicKey"),
- borsh.array(borsh.u8(), 32, "tapTweakHash"),
- borsh.i64("createdAt"),
- borsh.array(borsh.u8(), 32, "keyPathSpendPublicKey"),
- borsh.vec(
- borsh.struct([
- borsh.array(borsh.u8(), 32, "scriptPathSpendPublicKey"),
- borsh.i64("lockTime"),
- ]),
- "recoveryParameters"
- ),
- ]);
-
-export interface HotReserveBucket {
- publicKey: PublicKey;
- owner: PublicKey;
- guardianSetting: PublicKey;
- status: number;
- // Bitcoin Hot Reserve X-Only Public Key
- taprootXOnlyPublicKey: Uint8Array;
- tapTweakHash: Uint8Array;
- // Guardian X-Only PublicKey
- keyPathSpendPublicKey: Uint8Array;
- // User X-Only PublicKey
- scriptPathSpendPublicKey: Uint8Array;
- lockTime: BN;
- createdAt: BN;
- expiredAt: BN;
-}
-
-export const hotReserveBucketSchema: Structure = borsh.struct(
- [
- borsh.publicKey("owner"),
- borsh.publicKey("guardianSetting"),
- borsh.u8("status"),
- borsh.array(borsh.u8(), 32, "taprootXOnlyPublicKey"),
- borsh.array(borsh.u8(), 32, "tapTweakHash"),
- borsh.array(borsh.u8(), 32, "keyPathSpendPublicKey"),
- borsh.array(borsh.u8(), 32, "scriptPathSpendPublicKey"),
- borsh.u64("lockTime"),
- borsh.i64("createdAt"),
- borsh.i64("expiredAt"),
- ]
-);
-
-export enum HotReserveBucketStatus {
- Activated = 0,
- Deactivated = 1,
-}
-
-export interface Position {
- publicKey: PublicKey;
- owner: PublicKey;
- guardianSetting: PublicKey;
- storedAmount: BN;
- frozenAmount: BN;
- createdAt: BN;
- updatedAt: BN;
-}
-
-export const positionSchema: Structure = borsh.struct([
- borsh.publicKey("owner"),
- borsh.publicKey("guardianSetting"),
- borsh.u64("storedAmount"),
- borsh.u64("frozenAmount"),
- borsh.i64("createdAt"),
- borsh.i64("updatedAt"),
-]);
-
-// Instruction Schema for Serialization
-export interface CreateHotReserveBucket {
- discriminator: number;
- scriptPathSpendPublicKey: Uint8Array;
- lockTime: BN;
- validityPeriod: number;
-}
-
-export const createHotReserveBucketSchema: Structure =
- borsh.struct([
- borsh.u8("discriminator"),
- borsh.array(borsh.u8(), 32, "scriptPathSpendPublicKey"),
- borsh.u64("lockTime"),
- borsh.u32("validityPeriod"),
- ]);
-
-export interface ReactivateHotReserveBucket {
- discriminator: number;
- validityPeriod: number;
-}
-
-export const reactivateHotReserveBucketSchema: Structure =
- borsh.struct([borsh.u8("discriminator"), borsh.u32("validityPeriod")]);
-
-export interface AddWithdrawalRequest {
- discriminator: number;
- receiverAddress: Uint8Array;
- currentSlot: BN;
- withdrawalAmount: BN;
-}
-
-export const addWithdrawalRequestSchema: Structure =
- borsh.struct([
- borsh.u8("discriminator"),
- borsh.array(borsh.u8(), 32, "receiverAddress"),
- borsh.u64("currentSlot"),
- borsh.u64("withdrawalAmount"),
- ]);
-
-export interface Retrieve {
- discriminator: number;
- amount: BN;
-}
-
-export const retrieveSchema: Structure = borsh.struct([
- borsh.u8("discriminator"),
- borsh.u64("amount"),
-]);
-
-export interface Store {
- discriminator: number;
- amount: BN;
-}
-
-export const storeSchema: Structure = borsh.struct([
- borsh.u8("discriminator"),
- borsh.u64("amount"),
-]);
diff --git a/src/zplClient/account.ts b/src/zplClient/account.ts
deleted file mode 100644
index ba4781d2..00000000
--- a/src/zplClient/account.ts
+++ /dev/null
@@ -1,409 +0,0 @@
-import { Connection, PublicKey } from "@solana/web3.js";
-import BN from "bn.js";
-import bs58 from "bs58";
-import { sha256 } from "js-sha256";
-
-import { BitcoinXOnlyPublicKey } from "@/types/wallet";
-import {
- HotReserveBucket,
- hotReserveBucketSchema,
- positionSchema,
- Position,
- TwoWayPegConfiguration,
- twoWayPegConfigurationSchema,
- ColdReserveBucket,
- coldReserveBucketSchema,
-} from "@/types/zplClient";
-
-// Helper functions
-function generateAccountDiscriminator(input: string): Buffer {
- const preImage = Buffer.from(input);
- return Buffer.from(sha256(preImage), "hex").subarray(0, 8);
-}
-
-export function deserializeColdReserveBucket(
- publicKey: PublicKey,
- data?: Buffer
-): ColdReserveBucket {
- if (!data) throw new Error("Data is undefined");
-
- const {
- guardianSetting,
- owner,
- taprootXOnlyPublicKey,
- tapTweakHash,
- createdAt,
- keyPathSpendPublicKey,
- recoveryParameters,
- } = coldReserveBucketSchema.decode(data);
- return {
- publicKey,
- guardianSetting,
- owner,
- taprootXOnlyPublicKey,
- tapTweakHash,
- createdAt,
- keyPathSpendPublicKey,
- recoveryParameters,
- };
-}
-
-function deserializeHotReserveBucket(
- publicKey: PublicKey,
- data: Buffer | undefined
-): HotReserveBucket {
- if (!data) throw new Error("Data is undefined");
-
- const {
- owner,
- guardianSetting,
- status,
- taprootXOnlyPublicKey,
- tapTweakHash,
- keyPathSpendPublicKey,
- scriptPathSpendPublicKey,
- lockTime,
- createdAt,
- expiredAt,
- } = hotReserveBucketSchema.decode(data);
-
- return {
- publicKey,
- owner,
- guardianSetting,
- status,
- taprootXOnlyPublicKey,
- tapTweakHash,
- keyPathSpendPublicKey,
- scriptPathSpendPublicKey,
- lockTime,
- createdAt,
- expiredAt,
- };
-}
-
-function deserializePosition(
- publicKey: PublicKey,
- data: Buffer | undefined
-): Position {
- if (!data) throw new Error("Data is undefined");
-
- const {
- owner,
- guardianSetting,
- storedAmount,
- frozenAmount,
- createdAt,
- updatedAt,
- } = positionSchema.decode(data);
-
- return {
- publicKey,
- owner,
- guardianSetting,
- storedAmount,
- frozenAmount,
- createdAt,
- updatedAt,
- };
-}
-
-export function deserializeTwoWayPegConfiguration(
- publicKey: PublicKey,
- data: Buffer | undefined
-): TwoWayPegConfiguration {
- if (!data) throw new Error("Data is undefined");
-
- const {
- superOperatorCertificate,
- zeusColdReserveRecoveryPublicKey,
- zeusColdReserveRecoveryLockTime,
- layerFeeCollector,
- chadbufferAuthority,
- cpiIdentity,
- layerCaProgramId,
- bitcoinSpvProgramId,
- liquidityManagementProgramId,
- bucketOpenFeeAmount,
- bucketReactivationFeeAmount,
- withdrawalFeeAmount,
- minerFeeRate,
- } = twoWayPegConfigurationSchema.decode(data);
-
- return {
- publicKey,
- superOperatorCertificate,
- zeusColdReserveRecoveryPublicKey,
- zeusColdReserveRecoveryLockTime,
- layerFeeCollector,
- chadbufferAuthority,
- cpiIdentity,
- layerCaProgramId,
- bitcoinSpvProgramId,
- liquidityManagementProgramId,
- bucketOpenFeeAmount,
- bucketReactivationFeeAmount,
- withdrawalFeeAmount,
- minerFeeRate,
- };
-}
-
-export class AccountService {
- constructor(
- private connection: Connection,
- private twoWayPegProgramId: PublicKey,
- private liquidityManagementProgramId: PublicKey
- ) {}
-
- // Address derivation methods
- deriveConfigurationAddress() {
- const [configurationAddress] = PublicKey.findProgramAddressSync(
- [Buffer.from("configuration")],
- this.twoWayPegProgramId
- );
- return configurationAddress;
- }
-
- deriveCpiIdentityAddress() {
- return PublicKey.findProgramAddressSync(
- [Buffer.from("cpi-identity")],
- this.twoWayPegProgramId
- )[0];
- }
-
- deriveHotReserveBucketAddress(
- hotReserveBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey
- ): PublicKey {
- const bucketPda = PublicKey.findProgramAddressSync(
- [Buffer.from("hot-reserve-bucket"), hotReserveBitcoinXOnlyPublicKey],
- this.twoWayPegProgramId
- )[0];
- return bucketPda;
- }
-
- deriveInteraction(seed1: Buffer, seed2: BN) {
- const interactionPda = PublicKey.findProgramAddressSync(
- [
- Buffer.from("interaction"),
- // Deposit: transaction_id, Withdrawal: receiver_address
- seed1,
- // Deposit: v_out, Withdrawal: slot (u64 trimmed to u32)
- seed2.toArrayLike(Buffer, "le", 4),
- ],
- this.twoWayPegProgramId
- )[0];
-
- return interactionPda;
- }
-
- deriveLiquidityManagementConfigurationAddress() {
- const [configurationAddress] = PublicKey.findProgramAddressSync(
- [Buffer.from("configuration")],
- this.liquidityManagementProgramId
- );
-
- return configurationAddress;
- }
-
- deriveLiquidityManagementGuardianSettingAddress(
- twoWayPegGuardianSetting: PublicKey
- ) {
- const [guardianSettingAddress] = PublicKey.findProgramAddressSync(
- [Buffer.from("guardian-setting"), twoWayPegGuardianSetting.toBuffer()],
- this.liquidityManagementProgramId
- );
-
- return guardianSettingAddress;
- }
-
- deriveSplTokenVaultAuthorityAddress(twoWayPegGuardianSetting: PublicKey) {
- const [guardianSettingAddress] = PublicKey.findProgramAddressSync(
- [
- Buffer.from("spl-token-vault-authority"),
- twoWayPegGuardianSetting.toBuffer(),
- ],
- this.liquidityManagementProgramId
- );
-
- return guardianSettingAddress;
- }
-
- derivePositionAddress(
- lmGuardianSetting: PublicKey,
- userAddress: PublicKey | null
- ): PublicKey {
- return PublicKey.findProgramAddressSync(
- [
- Buffer.from("position"),
- lmGuardianSetting.toBuffer(),
- userAddress?.toBuffer() ?? Buffer.from([]),
- ],
- this.liquidityManagementProgramId
- )[0];
- }
-
- // Query methods
- async getTwoWayPegConfiguration() {
- const filters = [
- {
- memcmp: {
- offset: 0,
- bytes: bs58.encode(
- generateAccountDiscriminator("two-way-peg:configuration")
- ),
- },
- },
- ];
-
- const twoWayPegConfiguration = await this.connection.getProgramAccounts(
- this.twoWayPegProgramId,
- { filters }
- );
-
- const twoWayPegConfigurationData = twoWayPegConfiguration.map(
- (twoWayPegConfiguration) =>
- deserializeTwoWayPegConfiguration(
- twoWayPegConfiguration.pubkey,
- twoWayPegConfiguration.account.data.subarray(8)
- )
- );
-
- return twoWayPegConfigurationData[0];
- }
-
- async getColdReserveBuckets() {
- const filters = [
- {
- memcmp: {
- offset: 0,
- bytes: bs58.encode(
- generateAccountDiscriminator("two-way-peg:cold-reserve-bucket")
- ),
- },
- },
- ];
-
- const accounts = await this.connection.getProgramAccounts(
- this.twoWayPegProgramId,
- { filters }
- );
-
- const accountsData = accounts
- .map((account) => {
- const { data } = account.account;
- return deserializeColdReserveBucket(account.pubkey, data.subarray(8));
- })
- .toSorted((a, b) => b.createdAt.cmp(a.createdAt))
- .reduce((acc, current) => {
- if (
- !acc.some(
- (item) =>
- item.guardianSetting.toBase58() ===
- current.guardianSetting.toBase58()
- )
- ) {
- acc.push(current);
- }
- return acc;
- }, [] as ColdReserveBucket[]);
-
- return accountsData;
- }
-
- async getHotReserveBucketsByBitcoinXOnlyPubkey(
- bitcoinXOnlyPubkey: BitcoinXOnlyPublicKey
- ) {
- const filters = [
- {
- memcmp: {
- offset: 0,
- bytes: bs58.encode(
- generateAccountDiscriminator("two-way-peg:hot-reserve-bucket")
- ),
- },
- },
- {
- memcmp: {
- offset: 169,
- bytes: bs58.encode(bitcoinXOnlyPubkey),
- },
- },
- ];
-
- const hotReserveBuckets = await this.connection.getProgramAccounts(
- this.twoWayPegProgramId,
- { filters }
- );
-
- const hotReserveBucketsData = hotReserveBuckets.map((hotReserveBucket) =>
- deserializeHotReserveBucket(
- hotReserveBucket.pubkey,
- hotReserveBucket.account.data.subarray(8)
- )
- );
-
- return hotReserveBucketsData;
- }
-
- async getHotReserveBucketsBySolanaPubkey(solanaPubkey: PublicKey) {
- const filters = [
- {
- memcmp: {
- offset: 0,
- bytes: bs58.encode(
- generateAccountDiscriminator("two-way-peg:hot-reserve-bucket")
- ),
- },
- },
- {
- memcmp: {
- offset: 8,
- bytes: solanaPubkey.toBase58(),
- },
- },
- ];
-
- const hotReserveBuckets = await this.connection.getProgramAccounts(
- this.twoWayPegProgramId,
- { filters }
- );
-
- const hotReserveBucketsData = hotReserveBuckets.map((hotReserveBucket) =>
- deserializeHotReserveBucket(
- hotReserveBucket.pubkey,
- hotReserveBucket.account.data.subarray(8)
- )
- );
-
- return hotReserveBucketsData;
- }
-
- async getPositionsByWallet(solanaPubkey: PublicKey) {
- const filters = [
- {
- memcmp: {
- offset: 0,
- bytes: bs58.encode(
- generateAccountDiscriminator("liquidity-management:position")
- ),
- },
- },
- {
- memcmp: {
- offset: 8,
- bytes: solanaPubkey.toBase58(),
- },
- },
- ];
-
- const positions = await this.connection.getProgramAccounts(
- this.liquidityManagementProgramId,
- { filters }
- );
-
- return positions.map((position) => {
- const { data } = position.account;
- return deserializePosition(position.pubkey, data.subarray(8));
- });
- }
-}
diff --git a/src/zplClient/index.ts b/src/zplClient/index.ts
index d3e168d1..7cbae0f8 100644
--- a/src/zplClient/index.ts
+++ b/src/zplClient/index.ts
@@ -4,28 +4,25 @@ import {
PublicKey,
Transaction,
TransactionInstruction,
+ TransactionMessage,
VersionedTransaction,
} from "@solana/web3.js";
-import BN from "bn.js";
-
-import { BitcoinAddress, BitcoinXOnlyPublicKey } from "@/types/wallet";
-
-import { AccountService } from "./account";
-import { InstructionService } from "./instruction";
-import { RpcClient } from "./rpcClient";
+import {
+ LiquidityManagementClient,
+ TwoWayPegClient,
+} from "@zeus-network/zpl-sdk";
export class ZplClient {
- private accountService: AccountService;
- private instructionService: InstructionService;
- private rpcClient: RpcClient;
- private twoWayPegProgramId: PublicKey;
- private liquidityManagementProgramId: PublicKey;
- private assetMint: PublicKey;
+ public twoWayPegProgramId: PublicKey;
+ public liquidityManagementProgramId: PublicKey;
+ public assetMint: PublicKey;
+ public twoWayPeg: TwoWayPegClient;
+ public liquidityManagement: LiquidityManagementClient;
constructor(
- connection: Connection,
- walletPublicKey: PublicKey | null,
- signTransaction:
+ private connection: Connection,
+ private walletPublicKey: PublicKey | null,
+ private signTransaction:
| ((
transaction: T
) => Promise)
@@ -40,173 +37,53 @@ export class ZplClient {
);
this.assetMint = new PublicKey(assetMint);
- this.accountService = new AccountService(
- connection,
- this.twoWayPegProgramId,
- this.liquidityManagementProgramId
- );
-
- this.instructionService = new InstructionService(
- walletPublicKey,
- this.twoWayPegProgramId,
- this.liquidityManagementProgramId,
- this.assetMint,
- this.accountService
- );
+ this.twoWayPeg = new TwoWayPegClient(connection, this.twoWayPegProgramId);
- this.rpcClient = new RpcClient(
+ this.liquidityManagement = new LiquidityManagementClient(
connection,
- walletPublicKey,
- signTransaction
- );
- }
-
- // Account service methods
- deriveConfigurationAddress() {
- return this.accountService.deriveConfigurationAddress();
- }
-
- deriveCpiIdentityAddress() {
- return this.accountService.deriveCpiIdentityAddress();
- }
-
- deriveHotReserveBucketAddress(
- hotReserveBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey
- ): PublicKey {
- return this.accountService.deriveHotReserveBucketAddress(
- hotReserveBitcoinXOnlyPublicKey
+ this.liquidityManagementProgramId
);
}
- deriveInteraction(seed1: Buffer, seed2: BN) {
- return this.accountService.deriveInteraction(seed1, seed2);
- }
-
- deriveLiquidityManagementConfigurationAddress() {
- return this.accountService.deriveLiquidityManagementConfigurationAddress();
- }
-
- deriveLiquidityManagementGuardianSettingAddress(
- twoWayPegGuardianSetting: PublicKey
+ async signAndSendTransactionWithInstructions(
+ ixs: TransactionInstruction[],
+ lookupTableAccounts?: AddressLookupTableAccount[]
) {
- return this.accountService.deriveLiquidityManagementGuardianSettingAddress(
- twoWayPegGuardianSetting
- );
- }
+ const solanaPubkey = this.walletPublicKey;
+ const { signTransaction } = this;
- deriveSplTokenVaultAuthorityAddress(twoWayPegGuardianSetting: PublicKey) {
- return this.accountService.deriveSplTokenVaultAuthorityAddress(
- twoWayPegGuardianSetting
- );
- }
+ if (!solanaPubkey || !signTransaction)
+ throw new Error("Wallet is not connected");
- derivePositionAddress(
- lmGuardianSetting: PublicKey,
- userAddress: PublicKey | null
- ): PublicKey {
- return this.accountService.derivePositionAddress(
- lmGuardianSetting,
- userAddress
- );
- }
+ const { blockhash, lastValidBlockHeight } =
+ await this.connection.getLatestBlockhash();
- async getTwoWayPegConfiguration() {
- return this.accountService.getTwoWayPegConfiguration();
- }
-
- async getColdReserveBuckets() {
- return this.accountService.getColdReserveBuckets();
- }
-
- async getHotReserveBucketsByBitcoinXOnlyPubkey(
- bitcoinXOnlyPubkey: BitcoinXOnlyPublicKey
- ) {
- return this.accountService.getHotReserveBucketsByBitcoinXOnlyPubkey(
- bitcoinXOnlyPubkey
- );
- }
+ const msg = new TransactionMessage({
+ payerKey: solanaPubkey,
+ recentBlockhash: blockhash,
+ instructions: ixs,
+ }).compileToV0Message(lookupTableAccounts);
- async getHotReserveBucketsBySolanaPubkey(solanaPubkey: PublicKey) {
- return this.accountService.getHotReserveBucketsBySolanaPubkey(solanaPubkey);
- }
-
- async getPositionsByWallet(solanaPubkey: PublicKey) {
- return this.accountService.getPositionsByWallet(solanaPubkey);
- }
-
- // Instruction service methods
- constructCreateHotReserveBucketIx(
- solanaPubkey: PublicKey,
- hotReserveBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey,
- userBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey,
- unlockBlockHeight: number,
- guardianSetting: PublicKey,
- guardianCertificate: PublicKey,
- coldReserveBucket: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- return this.instructionService.constructCreateHotReserveBucketIx(
- solanaPubkey,
- hotReserveBitcoinXOnlyPublicKey,
- userBitcoinXOnlyPublicKey,
- unlockBlockHeight,
- guardianSetting,
- guardianCertificate,
- coldReserveBucket,
- layerFeeCollector
- );
- }
+ const tx = new VersionedTransaction(msg);
- constructReactivateHotReserveBucketIx(
- hotReserveBucketPda: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- return this.instructionService.constructReactivateHotReserveBucketIx(
- hotReserveBucketPda,
- layerFeeCollector
- );
- }
+ const signedTx = await signTransaction(tx);
- constructAddWithdrawalRequestIx(
- solanaPubkey: PublicKey,
- amount: BN,
- receiverAddress: BitcoinAddress,
- guardianSetting: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- return this.instructionService.constructAddWithdrawalRequestIx(
- solanaPubkey,
- amount,
- receiverAddress,
- guardianSetting,
- layerFeeCollector
+ const signature = await this.connection.sendRawTransaction(
+ signedTx.serialize(),
+ {
+ preflightCommitment: "confirmed",
+ }
);
- }
- constructRetrieveIx(
- amount: BN,
- guardianSetting: PublicKey,
- receiverAta: PublicKey
- ) {
- return this.instructionService.constructRetrieveIx(
- amount,
- guardianSetting,
- receiverAta
+ await this.connection.confirmTransaction(
+ {
+ signature,
+ lastValidBlockHeight,
+ blockhash,
+ },
+ "confirmed"
);
- }
- constructStoreIx(amount: BN, guardianSetting: PublicKey) {
- return this.instructionService.constructStoreIx(amount, guardianSetting);
- }
-
- // RPC client methods
- async signAndSendTransactionWithInstructions(
- ixs: TransactionInstruction[],
- lookupTableAccounts?: AddressLookupTableAccount[]
- ) {
- return this.rpcClient.signAndSendTransactionWithInstructions(
- ixs,
- lookupTableAccounts
- );
+ return signature;
}
}
diff --git a/src/zplClient/instruction.ts b/src/zplClient/instruction.ts
deleted file mode 100644
index 11c1f52b..00000000
--- a/src/zplClient/instruction.ts
+++ /dev/null
@@ -1,349 +0,0 @@
-import {
- ASSOCIATED_TOKEN_PROGRAM_ID,
- getAssociatedTokenAddressSync,
- TOKEN_PROGRAM_ID,
-} from "@solana/spl-token";
-import {
- PublicKey,
- SystemProgram,
- TransactionInstruction,
-} from "@solana/web3.js";
-import BN from "bn.js";
-
-import { BitcoinAddress, BitcoinXOnlyPublicKey } from "@/types/wallet";
-import {
- createHotReserveBucketSchema,
- retrieveSchema,
- storeSchema,
- addWithdrawalRequestSchema,
- reactivateHotReserveBucketSchema,
-} from "@/types/zplClient";
-import { HOT_RESERVE_BUCKET_VALIDITY_PERIOD } from "@/utils/constant";
-
-import { AccountService } from "./account";
-
-export class InstructionService {
- constructor(
- private walletPublicKey: PublicKey | null,
- private twoWayPegProgramId: PublicKey,
- private liquidityManagementProgramId: PublicKey,
- private assetMint: PublicKey,
- private accountService: AccountService
- ) {}
-
- constructCreateHotReserveBucketIx(
- solanaPubkey: PublicKey,
- hotReserveBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey,
- userBitcoinXOnlyPublicKey: BitcoinXOnlyPublicKey,
- unlockBlockHeight: number,
- guardianSetting: PublicKey,
- guardianCertificate: PublicKey,
- coldReserveBucket: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- const instructionData = Buffer.alloc(createHotReserveBucketSchema.span);
- createHotReserveBucketSchema.encode(
- {
- discriminator: 11,
- scriptPathSpendPublicKey: Uint8Array.from(userBitcoinXOnlyPublicKey),
- lockTime: new BN(unlockBlockHeight),
- validityPeriod: HOT_RESERVE_BUCKET_VALIDITY_PERIOD,
- },
- instructionData
- );
-
- const configurationPda = this.accountService.deriveConfigurationAddress();
-
- const hotReserveBucketPda =
- this.accountService.deriveHotReserveBucketAddress(
- hotReserveBitcoinXOnlyPublicKey
- );
-
- const ix = new TransactionInstruction({
- keys: [
- { pubkey: solanaPubkey, isSigner: true, isWritable: true },
- { pubkey: configurationPda, isSigner: false, isWritable: false },
- { pubkey: guardianSetting, isSigner: false, isWritable: false },
- { pubkey: guardianCertificate, isSigner: false, isWritable: false },
- { pubkey: coldReserveBucket, isSigner: false, isWritable: false },
- { pubkey: hotReserveBucketPda, isSigner: false, isWritable: true },
- {
- pubkey: layerFeeCollector,
- isSigner: false,
- isWritable: true,
- },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: true },
- ],
- programId: this.twoWayPegProgramId,
- data: instructionData,
- });
-
- return ix;
- }
-
- constructReactivateHotReserveBucketIx(
- hotReserveBucketPda: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- if (!this.walletPublicKey) throw new Error("Wallet is not connected");
-
- const instructionData = Buffer.alloc(reactivateHotReserveBucketSchema.span);
-
- reactivateHotReserveBucketSchema.encode(
- {
- discriminator: 13,
- validityPeriod: HOT_RESERVE_BUCKET_VALIDITY_PERIOD,
- },
- instructionData
- );
-
- const configurationPda = this.accountService.deriveConfigurationAddress();
-
- const ix = new TransactionInstruction({
- keys: [
- {
- pubkey: this.walletPublicKey,
- isSigner: true,
- isWritable: true,
- },
- { pubkey: configurationPda, isSigner: false, isWritable: false },
- { pubkey: hotReserveBucketPda, isSigner: false, isWritable: true },
- {
- pubkey: layerFeeCollector,
- isSigner: false,
- isWritable: true,
- },
- {
- pubkey: SystemProgram.programId,
- isSigner: false,
- isWritable: false,
- },
- ],
- programId: this.twoWayPegProgramId,
- data: instructionData,
- });
-
- return ix;
- }
-
- constructAddWithdrawalRequestIx(
- solanaPubkey: PublicKey,
- amount: BN,
- receiverAddress: BitcoinAddress,
- guardianSetting: PublicKey,
- layerFeeCollector: PublicKey
- ) {
- const withdrawalRequestSeed = new BN(Date.now() / 1000); // current slot as Unix timestamp
- const withdrawalRequestPda = PublicKey.findProgramAddressSync(
- [
- Buffer.from("withdrawal-request"),
- receiverAddress,
- withdrawalRequestSeed.toArrayLike(Buffer, "le", 4),
- ],
- this.twoWayPegProgramId
- )[0];
-
- const interactionPda = this.accountService.deriveInteraction(
- receiverAddress,
- withdrawalRequestSeed
- );
-
- const instructionData = Buffer.alloc(addWithdrawalRequestSchema.span);
- addWithdrawalRequestSchema.encode(
- {
- discriminator: 131,
- receiverAddress: Uint8Array.from(receiverAddress),
- currentSlot: new BN(Date.now() / 1000),
- withdrawalAmount: amount,
- },
- instructionData
- );
-
- const twoWayPegProgramCPIIdentity =
- this.accountService.deriveCpiIdentityAddress();
-
- const configurationPda = this.accountService.deriveConfigurationAddress();
-
- const lmGuardianSetting =
- this.accountService.deriveLiquidityManagementGuardianSettingAddress(
- guardianSetting
- );
-
- const positionPda = this.accountService.derivePositionAddress(
- lmGuardianSetting,
- solanaPubkey
- );
-
- const liquidityManagementConfiguration =
- this.accountService.deriveLiquidityManagementConfigurationAddress();
-
- const ix = new TransactionInstruction({
- keys: [
- { pubkey: solanaPubkey, isSigner: true, isWritable: true },
- {
- pubkey: twoWayPegProgramCPIIdentity,
- isSigner: false,
- isWritable: false,
- },
- { pubkey: configurationPda, isSigner: false, isWritable: false },
- { pubkey: guardianSetting, isSigner: false, isWritable: false },
- { pubkey: lmGuardianSetting, isSigner: false, isWritable: false },
- { pubkey: withdrawalRequestPda, isSigner: false, isWritable: true },
- { pubkey: interactionPda, isSigner: false, isWritable: true },
- { pubkey: positionPda, isSigner: false, isWritable: true },
- {
- pubkey: layerFeeCollector,
- isSigner: false,
- isWritable: true,
- },
- {
- pubkey: liquidityManagementConfiguration,
- isSigner: false,
- isWritable: false,
- },
- {
- pubkey: this.liquidityManagementProgramId,
- isSigner: false,
- isWritable: false,
- },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- ],
- programId: this.twoWayPegProgramId,
- data: instructionData,
- });
-
- return ix;
- }
-
- constructRetrieveIx(
- amount: BN,
- guardianSetting: PublicKey,
- receiverAta: PublicKey
- ) {
- if (!this.walletPublicKey) throw new Error("Wallet is not connected");
-
- const lmGuardianSetting =
- this.accountService.deriveLiquidityManagementGuardianSettingAddress(
- guardianSetting
- );
-
- const splTokenVaultAuthority =
- this.accountService.deriveSplTokenVaultAuthorityAddress(guardianSetting);
-
- const vaultAta = getAssociatedTokenAddressSync(
- this.assetMint,
- splTokenVaultAuthority,
- true
- );
-
- const positionPda = this.accountService.derivePositionAddress(
- lmGuardianSetting,
- this.walletPublicKey
- );
-
- const instructionData = Buffer.alloc(retrieveSchema.span);
- retrieveSchema.encode(
- {
- discriminator: 21,
- amount,
- },
- instructionData
- );
-
- const ix = new TransactionInstruction({
- keys: [
- {
- pubkey: this.walletPublicKey,
- isSigner: true,
- isWritable: true,
- },
- { pubkey: receiverAta, isSigner: false, isWritable: true },
- { pubkey: positionPda, isSigner: false, isWritable: true },
- { pubkey: lmGuardianSetting, isSigner: false, isWritable: false },
- { pubkey: splTokenVaultAuthority, isSigner: false, isWritable: false },
- { pubkey: vaultAta, isSigner: false, isWritable: true },
- { pubkey: this.assetMint, isSigner: false, isWritable: false },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
- {
- pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
- isSigner: false,
- isWritable: false,
- },
- ],
- programId: this.liquidityManagementProgramId,
- data: instructionData,
- });
-
- return ix;
- }
-
- constructStoreIx(amount: BN, guardianSetting: PublicKey) {
- if (!this.walletPublicKey) throw new Error("Wallet is not connected");
-
- const userAta = getAssociatedTokenAddressSync(
- this.assetMint,
- this.walletPublicKey,
- true
- );
-
- const lmGuardianSetting =
- this.accountService.deriveLiquidityManagementGuardianSettingAddress(
- guardianSetting
- );
-
- const splTokenVaultAuthority =
- this.accountService.deriveSplTokenVaultAuthorityAddress(guardianSetting);
-
- const vaultAta = getAssociatedTokenAddressSync(
- this.assetMint,
- splTokenVaultAuthority,
- true
- );
-
- const positionPda = this.accountService.derivePositionAddress(
- lmGuardianSetting,
- this.walletPublicKey
- );
-
- const lmConfiguration =
- this.accountService.deriveLiquidityManagementConfigurationAddress();
-
- const instructionData = Buffer.alloc(storeSchema.span);
- storeSchema.encode(
- {
- discriminator: 22,
- amount,
- },
- instructionData
- );
-
- const ix = new TransactionInstruction({
- keys: [
- {
- pubkey: this.walletPublicKey,
- isSigner: true,
- isWritable: true,
- },
- { pubkey: userAta, isSigner: false, isWritable: true },
- { pubkey: positionPda, isSigner: false, isWritable: true },
- {
- pubkey: lmConfiguration,
- isSigner: false,
- isWritable: false,
- },
- { pubkey: lmGuardianSetting, isSigner: false, isWritable: false },
- { pubkey: guardianSetting, isSigner: false, isWritable: false },
- { pubkey: splTokenVaultAuthority, isSigner: false, isWritable: false },
- { pubkey: vaultAta, isSigner: false, isWritable: true },
- { pubkey: this.assetMint, isSigner: false, isWritable: false },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
- ],
- programId: this.liquidityManagementProgramId,
- data: instructionData,
- });
-
- return ix;
- }
-}
diff --git a/src/zplClient/rpcClient.ts b/src/zplClient/rpcClient.ts
deleted file mode 100644
index 979aefc3..00000000
--- a/src/zplClient/rpcClient.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-import {
- AddressLookupTableAccount,
- Connection,
- PublicKey,
- Transaction,
- TransactionInstruction,
- TransactionMessage,
- VersionedTransaction,
-} from "@solana/web3.js";
-
-export class RpcClient {
- constructor(
- private connection: Connection,
- private walletPublicKey: PublicKey | null,
- private signTransaction:
- | ((
- transaction: T
- ) => Promise)
- | undefined
- ) {}
-
- async signAndSendTransactionWithInstructions(
- ixs: TransactionInstruction[],
- lookupTableAccounts?: AddressLookupTableAccount[]
- ) {
- const solanaPubkey = this.walletPublicKey;
- const { signTransaction } = this;
-
- if (!solanaPubkey || !signTransaction)
- throw new Error("Wallet is not connected");
-
- const { blockhash, lastValidBlockHeight } =
- await this.connection.getLatestBlockhash();
-
- const msg = new TransactionMessage({
- payerKey: solanaPubkey,
- recentBlockhash: blockhash,
- instructions: ixs,
- }).compileToV0Message(lookupTableAccounts);
-
- const tx = new VersionedTransaction(msg);
-
- const signedTx = await signTransaction(tx);
-
- const signature = await this.connection.sendRawTransaction(
- signedTx.serialize(),
- {
- preflightCommitment: "confirmed",
- }
- );
-
- await this.connection.confirmTransaction(
- {
- signature,
- lastValidBlockHeight,
- blockhash,
- },
- "confirmed"
- );
-
- return signature;
- }
-}