-
Notifications
You must be signed in to change notification settings - Fork 299
feat: add isWalletAddress endpoint #7626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
19e2f44
feat: add isWalletAddress endpoint
danielzhao122 04f0196
docs: include that custodial wallets address is not supported
danielzhao122 fe01aef
docs: include some more details on how to retrieve certain values
danielzhao122 4c86891
feat: add example scripts
danielzhao122 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| /** | ||
| * Verify that an address belongs to a wallet using the BitGo SDK. | ||
| * | ||
| * This example demonstrates using the SDK's isWalletAddress method which verifies: | ||
| * - Forwarder addresses (deposit addresses) | ||
| * - Base addresses (wallet contract addresses) | ||
| * | ||
| * Copyright 2024, BitGo, Inc. All Rights Reserved. | ||
| */ | ||
|
|
||
| const BitGoJS = require('bitgo'); | ||
|
|
||
| const coin = 'hteth'; // change to 'eth' for production | ||
| const env = 'test'; // change to 'prod' for production | ||
|
|
||
| // TODO: set your access token here | ||
| const accessToken = ''; | ||
|
|
||
| // TODO: set your wallet ID here | ||
| const walletId = ''; | ||
|
|
||
| async function main() { | ||
| // Initialize BitGo SDK | ||
| const bitgo = new BitGoJS.BitGo({ env, accessToken }); | ||
|
|
||
| console.log('Step 1: Getting wallet...'); | ||
| const wallet = await bitgo.coin(coin).wallets().get({ id: walletId }); | ||
|
|
||
| const coinSpecific = wallet.coinSpecific(); | ||
| const baseAddress = coinSpecific.baseAddress; | ||
| const walletVersion = coinSpecific.walletVersion; | ||
| const feeAddress = coinSpecific.feeAddress; | ||
| const walletSalt = coinSpecific.salt; | ||
|
|
||
| console.log(' Base Address:', baseAddress); | ||
| console.log(' Wallet Version:', walletVersion); | ||
|
|
||
| console.log('Step 2: Fetching keychains...'); | ||
| const keychainIds = wallet.keyIds(); | ||
| const keychains = []; | ||
|
|
||
| for (const keychainId of keychainIds) { | ||
| const keychain = await bitgo.coin(coin).keychains().get({ id: keychainId }); | ||
|
|
||
| // For TSS keychains, derive pub from commonKeychain (first 66 characters) | ||
| const pub = keychain.pub || (keychain.commonKeychain && keychain.commonKeychain.slice(0, 66)); | ||
|
|
||
| if (!pub) { | ||
| throw new Error(`Unable to derive pub for keychain ${keychainId}`); | ||
| } | ||
|
|
||
| keychains.push({ | ||
| pub: pub, | ||
| ...(keychain.ethAddress && { ethAddress: keychain.ethAddress }), | ||
| ...(keychain.commonKeychain && { commonKeychain: keychain.commonKeychain }) | ||
| }); | ||
| } | ||
| console.log(' Retrieved', keychains.length, 'keychains'); | ||
|
|
||
| console.log('Step 3: Getting address details...'); | ||
| const receiveAddress = wallet.receiveAddress(); | ||
| const addressObj = await wallet.getAddress({ address: receiveAddress }); | ||
|
|
||
| const addressIndex = addressObj.index; | ||
| const forwarderVersion = addressObj.coinSpecific?.forwarderVersion; | ||
| const forwarderSalt = addressObj.coinSpecific?.salt; | ||
|
|
||
| console.log(' Address:', receiveAddress); | ||
| console.log(' Index:', addressIndex); | ||
| console.log(' Forwarder Version:', forwarderVersion); | ||
|
|
||
| console.log('Step 4: Verifying forwarder address using SDK...'); | ||
| const forwarderParams = { | ||
| address: receiveAddress, | ||
| keychains: keychains, | ||
| baseAddress: baseAddress, | ||
| walletVersion: walletVersion, | ||
| index: addressIndex, | ||
| coinSpecific: { | ||
| forwarderVersion: forwarderVersion, | ||
| salt: forwarderSalt, | ||
| feeAddress: feeAddress, | ||
| baseAddress: baseAddress | ||
| } | ||
| }; | ||
|
|
||
| const forwarderResult = await wallet.baseCoin.isWalletAddress(forwarderParams); | ||
| console.log(' Result:', forwarderResult ? '✓ Valid' : '✗ Invalid'); | ||
|
|
||
| console.log('Step 5: Verifying base address using SDK...'); | ||
| const baseAddressParams = { | ||
| address: baseAddress, | ||
| keychains: keychains, | ||
| baseAddress: baseAddress, | ||
| walletVersion: walletVersion, | ||
| index: 0, | ||
| coinSpecific: { | ||
| salt: walletSalt, | ||
| feeAddress: feeAddress, | ||
| baseAddress: baseAddress | ||
| } | ||
| }; | ||
|
|
||
| const baseResult = await wallet.baseCoin.isWalletAddress(baseAddressParams); | ||
| console.log(' Result:', baseResult ? '✓ Valid' : '✗ Invalid'); | ||
|
|
||
| console.log('\n' + (forwarderResult && baseResult ? '✅ Success: Both addresses verified' : '❌ Failed: Verification failed')); | ||
| } | ||
|
|
||
| main().catch((e) => console.error(e)); | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| /** | ||
| * Verify that an address belongs to a wallet using the BitGo Express API. | ||
| * | ||
| * This example demonstrates the isWalletAddress endpoint which verifies: | ||
| * - Forwarder addresses (deposit addresses) | ||
| * - Base addresses (wallet contract addresses) | ||
| * | ||
| * Copyright 2024, BitGo, Inc. All Rights Reserved. | ||
| */ | ||
|
|
||
| const fetch = require('node-fetch'); | ||
|
|
||
| const coin = 'hteth'; // change to 'eth' for production | ||
|
|
||
| // TODO: set your access token here | ||
| const accessToken = ''; | ||
|
|
||
| // TODO: set your wallet ID here | ||
| const walletId = ''; | ||
|
|
||
| const expressUrl = ''; | ||
|
|
||
| // Helper function to make API requests to Express | ||
| async function apiRequest(method, endpoint, body = null) { | ||
| const response = await fetch(`${expressUrl}${endpoint}`, { | ||
| method, | ||
| headers: { | ||
| 'Authorization': `Bearer ${accessToken}`, | ||
| 'Content-Type': 'application/json' | ||
| }, | ||
| body: body ? JSON.stringify(body) : null | ||
| }); | ||
|
|
||
| if (!response.ok) { | ||
| throw new Error(`HTTP ${response.status}: ${await response.text()}`); | ||
| } | ||
|
|
||
| return await response.json(); | ||
| } | ||
|
|
||
| async function main() { | ||
| console.log('Step 1: Fetching wallet data...'); | ||
| const wallet = await apiRequest('GET', `/api/v2/${coin}/wallet/${walletId}`); | ||
|
|
||
| const keychainIds = wallet.keys; | ||
| const baseAddress = wallet.coinSpecific.baseAddress; | ||
| const walletVersion = wallet.coinSpecific.walletVersion; | ||
| const feeAddress = wallet.coinSpecific.feeAddress; | ||
| const walletSalt = wallet.coinSpecific.salt; | ||
| const addressToVerify = wallet.receiveAddress.address; | ||
|
|
||
| console.log(' Base Address:', baseAddress); | ||
| console.log(' Wallet Version:', walletVersion); | ||
|
|
||
| console.log('Step 2: Fetching keychains...'); | ||
| const keychains = []; | ||
| for (const keychainId of keychainIds) { | ||
| const keychain = await apiRequest('GET', `/api/v2/${coin}/key/${keychainId}`); | ||
|
|
||
| // For TSS keychains, derive pub from commonKeychain (first 66 characters) | ||
| const pub = keychain.pub || (keychain.commonKeychain && keychain.commonKeychain.slice(0, 66)); | ||
|
|
||
| if (!pub) { | ||
| throw new Error(`Unable to derive pub for keychain ${keychainId}`); | ||
| } | ||
|
|
||
| keychains.push({ | ||
| pub: pub, | ||
| ...(keychain.ethAddress && { ethAddress: keychain.ethAddress }), | ||
| ...(keychain.commonKeychain && { commonKeychain: keychain.commonKeychain }) | ||
| }); | ||
| } | ||
| console.log(' Retrieved', keychains.length, 'keychains'); | ||
|
|
||
| console.log('Step 3: Fetching address details...'); | ||
| const addressData = await apiRequest('GET', `/api/v2/${coin}/wallet/${walletId}/address/${addressToVerify}`); | ||
|
|
||
| const addressIndex = addressData.index; | ||
| const forwarderVersion = addressData.coinSpecific?.forwarderVersion; | ||
| const forwarderSalt = addressData.coinSpecific?.salt; | ||
|
|
||
| console.log(' Address:', addressToVerify); | ||
| console.log(' Index:', addressIndex); | ||
| console.log(' Forwarder Version:', forwarderVersion); | ||
|
|
||
| console.log('Step 4: Verifying forwarder address...'); | ||
| const forwarderParams = { | ||
| address: addressToVerify, | ||
| keychains: keychains, | ||
| baseAddress: baseAddress, | ||
| walletVersion: walletVersion, | ||
| index: addressIndex, | ||
| coinSpecific: { | ||
| forwarderVersion: forwarderVersion, | ||
| salt: forwarderSalt, | ||
| feeAddress: feeAddress, | ||
| baseAddress: baseAddress | ||
| } | ||
| }; | ||
|
|
||
| const forwarderResult = await apiRequest('POST', `/api/v2/${coin}/wallet/${walletId}/iswalletaddress`, forwarderParams); | ||
| console.log(' Result:', forwarderResult ? '✓ Valid' : '✗ Invalid'); | ||
|
|
||
| console.log('Step 5: Verifying base address...'); | ||
| const baseAddressParams = { | ||
| address: baseAddress, | ||
| keychains: keychains, | ||
| baseAddress: baseAddress, | ||
| walletVersion: walletVersion, | ||
| index: 0, | ||
| coinSpecific: { | ||
| salt: walletSalt, | ||
| feeAddress: feeAddress, | ||
| baseAddress: baseAddress | ||
| } | ||
| }; | ||
|
|
||
| const baseResult = await apiRequest('POST', `/api/v2/${coin}/wallet/${walletId}/iswalletaddress`, baseAddressParams); | ||
| console.log(' Result:', baseResult ? '✓ Valid' : '✗ Invalid'); | ||
| } | ||
|
|
||
| main().catch((e) => console.error(e)); | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.