Skip to content

Commit

Permalink
feat: add ledger-xrp-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
Polybius93 committed Oct 15, 2024
1 parent 9810560 commit 112d065
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 11 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
},
"dependencies": {
"@ledgerhq/hw-app-btc": "10.4.1",
"@ledgerhq/hw-app-xrp": "6.29.4",
"@noble/hashes": "1.4.0",
"@scure/base": "1.1.8",
"@scure/btc-signer": "1.3.2",
Expand All @@ -72,6 +73,7 @@
"ledger-bitcoin": "0.2.3",
"prompts": "2.4.2",
"ramda": "0.30.1",
"ripple-binary-codec": "^2.1.0",
"scure": "1.6.0",
"tiny-secp256k1": "2.2.3",
"xrpl": "4.0.0"
Expand Down
14 changes: 5 additions & 9 deletions src/functions/ripple/ripple.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,13 @@ export async function signAndSubmitRippleTransaction(

export async function getLockedBTCBalance(
rippleClient: Client,
rippleWallet: Wallet,
userAddress: string,
issuerAddress: string
): Promise<number> {
try {
await connectRippleClient(rippleClient);

const rippleVaults = await getAllRippleVaults(
rippleClient,
issuerAddress,
rippleWallet.classicAddress
);
const rippleVaults = await getAllRippleVaults(rippleClient, issuerAddress, userAddress);

const lockedBTCBalance = rippleVaults.reduce((accumulator, vault) => {
return accumulator + vault.valueLocked.toNumber();
Expand All @@ -298,15 +294,15 @@ export async function getLockedBTCBalance(

export async function getDLCBTCBalance(
rippleClient: Client,
rippleWallet: Wallet,
userAddress: string,
issuerAddress: string
): Promise<number> {
try {
await connectRippleClient(rippleClient);

const accountNonXRPBalancesRequest: AccountLinesRequest = {
command: 'account_lines',
account: rippleWallet.classicAddress,
account: userAddress,
ledger_index: 'validated',
};

Expand Down Expand Up @@ -334,7 +330,7 @@ export async function createCheck(
destinationTag: number = 1,
dlcBTCAmount: string,
vaultUUID: string
): Promise<Transaction> {
): Promise<CheckCreate> {
try {
await connectRippleClient(rippleClient);

Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { PrivateKeyDLCHandler } from './dlc-handlers/private-key-dlc-handler.js'
import { SoftwareWalletDLCHandler } from './dlc-handlers/software-wallet-dlc-handler.js';
import { EthereumHandler } from './network-handlers/ethereum-handler.js';
import { RippleHandler } from './network-handlers/ripple-handler.js';
import { LedgerXRPHandler } from './network-handlers/xrp-ledger-handler.js';
import { ProofOfReserveHandler } from './proof-of-reserve-handlers/proof-of-reserve-handler.js';

export {
PrivateKeyDLCHandler,
LedgerDLCHandler,
SoftwareWalletDLCHandler,
LedgerXRPHandler,
EthereumHandler,
ProofOfReserveHandler,
RippleHandler,
Expand Down
146 changes: 146 additions & 0 deletions src/network-handlers/xrp-ledger-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import Xrp from '@ledgerhq/hw-app-xrp';
import { encode } from 'ripple-binary-codec';
import { CheckCreate, Client, Transaction, TrustSet } from 'xrpl';

import {
checkRippleTransactionResult,
connectRippleClient,
createCheck,
getDLCBTCBalance,
getLockedBTCBalance,
setTrustLine,
} from '../functions/ripple/ripple.functions.js';

export class LedgerXRPHandler {
private ledgerApp: Xrp.default;
private derivationPath: string;
private xrpClient: Client;
private issuerAddress: string;

constructor(
ledgerApp: Xrp.default,
derivationPath: string,
xrpClient: Client,
issuerAddress: string
) {
this.ledgerApp = ledgerApp;
this.derivationPath = derivationPath;
this.xrpClient = xrpClient;
this.issuerAddress = issuerAddress;
}

public async getAddress(): Promise<string> {
const address = await this.ledgerApp.getAddress(this.derivationPath);
return address.address;
}

public async setTrustLine(): Promise<void> {
try {
const deviceData = await this.ledgerApp.getAddress(this.derivationPath);

const trustLineRequest = await setTrustLine(
this.xrpClient,
deviceData.address,
this.issuerAddress
);

if (!trustLineRequest) {
console.error('TrustLine is already set');
return;
}
const updatedTrustLineRequest: TrustSet = {
...trustLineRequest,
Flags: 2147483648,
SigningPubKey: deviceData.publicKey.toUpperCase(),
};

const encodedTrustLineRequest = encode(updatedTrustLineRequest);

const signature = await this.ledgerApp.signTransaction(
this.derivationPath,
encodedTrustLineRequest
);
console.log('Signature:', signature);

const signedTrustLineRequest: TrustSet = {
...updatedTrustLineRequest,
TxnSignature: signature,
};

await connectRippleClient(this.xrpClient);

const submitTrustLineRequestResponse =
await this.xrpClient.submitAndWait(signedTrustLineRequest);

console.log(`Response for submitted Transaction Request:`, submitTrustLineRequestResponse);

checkRippleTransactionResult(submitTrustLineRequestResponse);
} catch (error) {
throw new Error(`Error setting Trust Line: ${error}`);
}
}

public async createCheck(dlcBTCAmount: string, vaultUUID: string): Promise<void> {
try {
const deviceData = await this.ledgerApp.getAddress(this.derivationPath);

const checkCreateRequest: CheckCreate = await createCheck(
this.xrpClient,
deviceData.address,
this.issuerAddress,
undefined,
dlcBTCAmount,
vaultUUID
);

const updatedCheckCreateRequest: CheckCreate = {
...checkCreateRequest,
Flags: 2147483648,
SigningPubKey: deviceData.publicKey.toUpperCase(),
};

const encodedCheckCreateRequest = encode(updatedCheckCreateRequest);

const signature = await this.ledgerApp.signTransaction(
this.derivationPath,
encodedCheckCreateRequest
);

const signedCheckCreateRequest: Transaction = {
...updatedCheckCreateRequest,
TxnSignature: signature,
};

await connectRippleClient(this.xrpClient);

const submitCheckCreateRequestResponse =
await this.xrpClient.submitAndWait(signedCheckCreateRequest);

console.log(`Response for submitted Transaction Request:`, submitCheckCreateRequestResponse);

checkRippleTransactionResult(submitCheckCreateRequestResponse);
} catch (error) {
throw new Error(`Error creating Check: ${error}`);
}
}

public async getDLCBTCBalance(): Promise<number> {
try {
const deviceData = await this.ledgerApp.getAddress(this.derivationPath);

return await getDLCBTCBalance(this.xrpClient, deviceData.address, this.issuerAddress);
} catch (error) {
throw new Error(`Error getting BTC Balance: ${error}`);
}
}

public async getLockedBTCBalance(): Promise<number> {
try {
const deviceData = await this.ledgerApp.getAddress(this.derivationPath);

return await getLockedBTCBalance(this.xrpClient, deviceData.address, this.issuerAddress);
} catch (error) {
throw new Error(`Error getting BTC Balance: ${error}`);
}
}
}
12 changes: 10 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,14 @@
tiny-secp256k1 "1.1.6"
varuint-bitcoin "1.1.2"

"@ledgerhq/[email protected]":
version "6.29.4"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-xrp/-/hw-app-xrp-6.29.4.tgz#b90d847f2cf8ddca9ca0068f5079f199c334314d"
integrity sha512-fEnqkwmEmcThGVtxLUQX9x4KB1E659Ke1dYuCZSXX4346+h3PCa7cfeKN/VRZNH8HQJgiYi53LqqYzwWXB5zbg==
dependencies:
"@ledgerhq/hw-transport" "^6.31.4"
bip32-path "0.4.2"

"@ledgerhq/hw-transport@^6.20.0":
version "6.30.6"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.30.6.tgz#c6d84672ac4828f311831998f4101ea205215a6d"
Expand All @@ -1115,7 +1123,7 @@
"@ledgerhq/logs" "^6.12.0"
events "^3.3.0"

"@ledgerhq/hw-transport@^6.31.2":
"@ledgerhq/hw-transport@^6.31.2", "@ledgerhq/hw-transport@^6.31.4":
version "6.31.4"
resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.31.4.tgz#9b23a6de4a4caaa5c24b149c2dea8adde46f0eb1"
integrity sha512-6c1ir/cXWJm5dCWdq55NPgCJ3UuKuuxRvf//Xs36Bq9BwkV2YaRQhZITAkads83l07NAdR16hkTWqqpwFMaI6A==
Expand Down Expand Up @@ -1792,7 +1800,7 @@ bip174@^2.0.1, bip174@^2.1.1:
resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.1.tgz#ef3e968cf76de234a546962bcf572cc150982f9f"
integrity sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==

bip32-path@^0.4.2:
bip32-path@0.4.2, bip32-path@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/bip32-path/-/bip32-path-0.4.2.tgz#5db0416ad6822712f077836e2557b8697c0c7c99"
integrity sha512-ZBMCELjJfcNMkz5bDuJ1WrYvjlhEF5k6mQ8vUr4N7MbVRsXei7ZOg8VhhwMfNiW68NWmLkgkc6WvTickrLGprQ==
Expand Down

0 comments on commit 112d065

Please sign in to comment.