Skip to content
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

feat: add cash check by tx id function #33

Merged
merged 3 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"type": "module",
"name": "dlc-btc-lib",
"version": "2.4.3",
"version": "2.4.5",
"description": "This library provides a comprehensive set of interfaces and functions for minting dlcBTC tokens on supported blockchains.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions src/constants/ripple.constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
import { convertStringToHex } from 'xrpl';

export const TRANSACTION_SUCCESS_CODE = 'tesSUCCESS';
export const XRPL_DLCBTC_CURRENCY_HEX = convertStringToHex('dlcBTC').padEnd(40, '0');
5 changes: 5 additions & 0 deletions src/functions/attestor/attestor-request.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ export async function submitSetupXRPLVaultRequest(
return sendRequest(`${coordinatorURL}/app/setup-xrpl-vault`, requestBody);
}

export async function submitXRPLCheckToCash(coordinatorURL: string, txHash: string): Promise<void> {
const requestBody = JSON.stringify({ tx_hash: txHash });
return sendRequest(`${coordinatorURL}/app/cash-xrpl-check`, requestBody);
}

export async function getAttestorExtendedGroupPublicKey(coordinatorURL: string): Promise<string> {
return sendGetRequest(`${coordinatorURL}/tss/get-extended-group-publickey`);
}
Expand Down
1 change: 1 addition & 0 deletions src/functions/attestor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export {
submitWithdrawDepositPSBT,
getAttestorExtendedGroupPublicKey,
submitSetupXRPLVaultRequest,
submitXRPLCheckToCash,
} from '../attestor/attestor-request.functions.js';
48 changes: 43 additions & 5 deletions src/functions/ripple/ripple.functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import {
AccountLinesResponse,
AccountNFToken,
AccountNFTsRequest,
AccountObjectsRequest,
CheckCreate,
Client,
LedgerEntry,
SubmittableTransaction,
Transaction,
TransactionMetadataBase,
Expand All @@ -17,7 +19,10 @@ import {
convertStringToHex,
} from 'xrpl';

import { TRANSACTION_SUCCESS_CODE } from '../../constants/ripple.constants.js';
import {
TRANSACTION_SUCCESS_CODE,
XRPL_DLCBTC_CURRENCY_HEX,
} from '../../constants/ripple.constants.js';
import { RippleError } from '../../models/errors.js';
import { RawVault } from '../../models/ethereum-models.js';
import { SignResponse } from '../../models/ripple.model.js';
Expand Down Expand Up @@ -165,7 +170,9 @@ export async function setTrustLine(
result: { lines },
}: AccountLinesResponse = await rippleClient.request(accountNonXRPBalancesRequest);

if (lines.some(line => line.currency === 'BTC' && line.account === issuerAddress)) {
if (
lines.some(line => line.currency === XRPL_DLCBTC_CURRENCY_HEX && line.account === issuerAddress)
) {
console.log(`Trust Line already exists for Issuer: ${issuerAddress}`);
return;
}
Expand All @@ -174,7 +181,7 @@ export async function setTrustLine(
TransactionType: 'TrustSet',
Account: ownerAddress,
LimitAmount: {
currency: 'BTC',
currency: XRPL_DLCBTC_CURRENCY_HEX,
issuer: issuerAddress,
value: '10000000000',
},
Expand Down Expand Up @@ -312,7 +319,7 @@ export async function getDLCBTCBalance(
}: AccountLinesResponse = await rippleClient.request(accountNonXRPBalancesRequest);

const dlcBTCBalance = lines.find(
line => line.currency === 'BTC' && line.account === issuerAddress
line => line.currency === XRPL_DLCBTC_CURRENCY_HEX && line.account === issuerAddress
);
if (!dlcBTCBalance) {
return 0;
Expand Down Expand Up @@ -346,7 +353,7 @@ export async function createCheck(
Destination: destinationAddress,
DestinationTag: destinationTag,
SendMax: {
currency: 'BTC',
currency: XRPL_DLCBTC_CURRENCY_HEX,
value: shiftedAmountAsNumber.toString(),
issuer: destinationAddress,
},
Expand All @@ -361,3 +368,34 @@ export async function createCheck(
throw new RippleError(`Error creating Check for Vault ${vaultUUID}: ${error}`);
}
}

export async function getCheckByTXHash(
rippleClient: Client,
issuerAddress: string,
txHash: string
): Promise<LedgerEntry.Check> {
try {
await connectRippleClient(rippleClient);

const getAccountObjectsRequest: AccountObjectsRequest = {
command: 'account_objects',
account: issuerAddress,
ledger_index: 'validated',
type: 'check',
};

const {
result: { account_objects },
} = await rippleClient.request(getAccountObjectsRequest);

const check = account_objects.find(accountObject => accountObject.PreviousTxnID === txHash);

if (!check) {
throw new RippleError(`Check with TX Hash: ${txHash} not found`);
}

return check as LedgerEntry.Check;
} catch (error) {
throw new RippleError(`Error getting Check by TX Hash: ${error}`);
}
}
79 changes: 34 additions & 45 deletions src/network-handlers/ripple-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import xrpl, {
AccountObjectsResponse,
CheckCash,
IssuedCurrencyAmount,
LedgerEntry,
Payment,
Request,
SubmittableTransaction,
} from 'xrpl';
import { NFTokenMintMetadata } from 'xrpl/dist/npm/models/transactions/NFTokenMint.js';

import { decodeURI, encodeURI } from '../functions/ripple/ripple.functions.js';
import { XRPL_DLCBTC_CURRENCY_HEX } from '../constants/ripple.constants.js';
import {
connectRippleClient,
decodeURI,
encodeURI,
getCheckByTXHash,
} from '../functions/ripple/ripple.functions.js';
import { RippleError } from '../models/errors.js';
import { RawVault, SSFVaultUpdate, SSPVaultUpdate } from '../models/ethereum-models.js';
import { shiftValue, unshiftValue } from '../utilities/index.js';
Expand Down Expand Up @@ -130,6 +135,7 @@ export class RippleHandler {
const getNFTsTransaction: AccountNFTsRequest = {
command: 'account_nfts',
account: this.issuerAddress,
limit: 400,
};
let nftUUID = uuid.substring(0, 2) === '0x' ? uuid.slice(2) : uuid;
nftUUID = nftUUID.toUpperCase();
Expand Down Expand Up @@ -357,6 +363,7 @@ export class RippleHandler {
const getNFTsTransaction: AccountNFTsRequest = {
command: 'account_nfts',
account: this.issuerAddress,
limit: 400,
};

const nfts: xrpl.AccountNFTsResponse = await this.client.request(getNFTsTransaction);
Expand Down Expand Up @@ -506,55 +513,37 @@ export class RippleHandler {
return getAccountObjectsResponse.result.account_objects;
}

async getAndCashAllChecksAndUpdateNFT(): Promise<string[]> {
const allChecks = (await this.getAllChecks()) as LedgerEntry.Check[];
// console.log('All Checks:', allChecks);
const allVaults = await this.getContractVaults();
async getCashCheckAndWithdrawSignatures(txHash: string): Promise<string[]> {
try {
const check = await getCheckByTXHash(this.client, this.issuerAddress, txHash);
const invoiceID = check.InvoiceID;

for (const check of allChecks) {
try {
const checkSendMax = check.SendMax as IssuedCurrencyAmount;
if (!invoiceID) {
throw new RippleError(`Could not find Invoice ID for Check with TX Hash: ${txHash}`);
}

const my_check_cash_sig = await this.cashCheck(check.index, checkSendMax.value);
const vault = await this.getRawVault(`0x${invoiceID}`.toLowerCase());

const vault = allVaults.find(
vault => vault.uuid.toUpperCase().slice(2) === check.InvoiceID
);
if (!vault) {
throw new RippleError(
`Could not find Vault for Check with Invoice ID: ${check.InvoiceID}`
);
}
const two_more_sigs = await this.withdraw(
vault.uuid,
BigInt(shiftValue(Number(checkSendMax.value)))
);
return [my_check_cash_sig, ...two_more_sigs];
} catch (error) {
console.error(`Error cashing Check: ${error} \n continuing`);
if (!vault) {
throw new RippleError(`Could not find Vault for Check with Invoice ID: ${check.InvoiceID}`);
}

const checkSendMax = check.SendMax as IssuedCurrencyAmount;

const checkCashSignatures = await this.cashCheck(check.index, checkSendMax.value);

const mintAndBurnSignatures = await this.withdraw(
vault.uuid,
BigInt(shiftValue(Number(checkSendMax.value)))
);
return [checkCashSignatures, ...mintAndBurnSignatures];
} catch (error) {
throw new RippleError(`Could not get Cash Check and Withdraw Signatures: ${error}`);
}
return [];
}

async cashCheck(checkID: string, dlcBTCAmount: string): Promise<string> {
if (!this.client.isConnected()) {
await this.client.connect();
}

//what's
if (
[
'8FC923A16C90FB7316673D35CA228C82916B8E9F63EADC57BAA7C51C2E7716AA',
'AD2F46F345B07A070CBB0797D47D4D1A6CAA2BB541A0932014B909194665E4D5',
'DDF48640BF7DBC84FD08C1129999415CF5745095871FA6E50F1EAEB8AB032654',
'BA8B88BC1FD746F538AA6EFD1F1BFC982E3CCDD93EDDCFB4541EA608B355D778',
'48A7965799596CDA23C774778CD2D65E3E7C01648077539840A51ABD54791E32',
'93BAA031806AE4902933C1EE9B66E7EBAF0F7A182314085BEFF99DF080A1CBCB',
'F51C7E3CCFD2EC8CA9A460A34C5BC185E9466031865E76736C0A60BC3F7C7316',
].includes(checkID)
)
throw new Error('Invalid Check');
await connectRippleClient(this.client);

console.log(`Cashing Check of Check ID ${checkID} for an amount of ${dlcBTCAmount}`);

Expand All @@ -563,7 +552,7 @@ export class RippleHandler {
Account: this.issuerAddress,
CheckID: checkID,
Amount: {
currency: 'BTC',
currency: XRPL_DLCBTC_CURRENCY_HEX,
value: dlcBTCAmount,
issuer: this.issuerAddress,
},
Expand Down Expand Up @@ -616,7 +605,7 @@ export class RippleHandler {
Destination: destinationAddress,
DestinationTag: 1,
Amount: {
currency: 'BTC',
currency: XRPL_DLCBTC_CURRENCY_HEX,
value: dlcBTCAmount,
issuer: this.issuerAddress,
},
Expand Down
24 changes: 21 additions & 3 deletions src/network-handlers/xrp-gem-wallet-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getAddress, signTransaction } from '@gemwallet/api';
import { ResponseType } from '@gemwallet/api/_constants/index.js';
import { CheckCreate, Client, TrustSet } from 'xrpl';

import { submitXRPLCheckToCash } from '../functions/attestor/attestor-request.functions.js';
import {
checkRippleTransactionResult,
connectRippleClient,
Expand Down Expand Up @@ -73,7 +74,7 @@ export class GemXRPHandler {
}
}

public async createCheck(dlcBTCAmount: string, vaultUUID: string): Promise<void> {
public async createCheck(dlcBTCAmount: string, vaultUUID: string): Promise<CheckCreate> {
try {
const checkCreateRequest: CheckCreate = await createCheck(
this.xrpClient,
Expand All @@ -89,8 +90,16 @@ export class GemXRPHandler {
Flags: 2147483648,
};

return updatedCheckCreateRequest;
} catch (error) {
throw new Error(`Error creating Check: ${error}`);
}
}

public async signAndSubmitCheck(checkCreateRequest: CheckCreate): Promise<string> {
try {
const signCheckCreateResponse = await signTransaction({
transaction: updatedCheckCreateRequest,
transaction: checkCreateRequest,
});

if (
Expand All @@ -111,11 +120,20 @@ export class GemXRPHandler {
console.log(`Response for submitted Transaction Request:`, submitCheckCreateRequestResponse);

checkRippleTransactionResult(submitCheckCreateRequestResponse);

return submitCheckCreateRequestResponse.result.hash;
} catch (error) {
throw new Error(`Error creating Check: ${error}`);
throw new Error(`Error signing and submitting Check: ${error}`);
}
}

public async sendCheckTXHash(coordinatorURL: string, checkTXHash: string): Promise<void> {
try {
await submitXRPLCheckToCash(coordinatorURL, checkTXHash);
} catch (error) {
throw new Error(`Error sending Check TX Hash to Attestors: ${error}`);
}
}
public async getDLCBTCBalance(): Promise<number> {
try {
await connectRippleClient(this.xrpClient);
Expand Down
27 changes: 23 additions & 4 deletions src/network-handlers/xrp-ledger-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as Xrp from '@ledgerhq/hw-app-xrp';
import { encode } from 'ripple-binary-codec';
import { CheckCreate, Client, Transaction, TrustSet } from 'xrpl';

import { submitXRPLCheckToCash } from '../functions/attestor/attestor-request.functions.js';
import {
checkRippleTransactionResult,
connectRippleClient,
Expand Down Expand Up @@ -84,7 +85,7 @@ export class LedgerXRPHandler {
}
}

public async createCheck(dlcBTCAmount: string, vaultUUID: string): Promise<void> {
public async createCheck(dlcBTCAmount: string, vaultUUID: string): Promise<CheckCreate> {
try {
const checkCreateRequest: CheckCreate = await createCheck(
this.xrpClient,
Expand All @@ -101,15 +102,23 @@ export class LedgerXRPHandler {
SigningPubKey: this.publicKey.toUpperCase(),
};

const encodedCheckCreateRequest = encode(updatedCheckCreateRequest);
return updatedCheckCreateRequest;
} catch (error) {
throw new Error(`Error creating Check: ${error}`);
}
}

public async signAndSubmitCheck(checkCreateRequest: CheckCreate): Promise<string> {
try {
const encodedCheckCreateRequest = encode(checkCreateRequest);

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

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

Expand All @@ -121,8 +130,18 @@ export class LedgerXRPHandler {
console.log(`Response for submitted Transaction Request:`, submitCheckCreateRequestResponse);

checkRippleTransactionResult(submitCheckCreateRequestResponse);

return submitCheckCreateRequestResponse.result.hash;
} catch (error) {
throw new Error(`Error creating Check: ${error}`);
throw new Error(`Error signing and submitting Check: ${error}`);
}
}

public async sendCheckTXHash(coordinatorURL: string, checkTXHash: string): Promise<void> {
try {
await submitXRPLCheckToCash(coordinatorURL, checkTXHash);
} catch (error) {
throw new Error(`Error sending Check TX Hash to Attestors: ${error}`);
}
}

Expand Down
Loading