Skip to content

Commit

Permalink
add sugar method
Browse files Browse the repository at this point in the history
  • Loading branch information
mvadari committed Jan 6, 2025
1 parent 96d2a71 commit 78b1c20
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 20 deletions.
68 changes: 67 additions & 1 deletion packages/xrpl/src/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import type {
MarkerRequest,
MarkerResponse,
SubmitResponse,
SimulateResponse,
SimulateRequest,
} from '../models/methods'
import type { BookOffer, BookOfferCurrency } from '../models/methods/bookOffers'
import type {
Expand Down Expand Up @@ -74,7 +76,7 @@ import {
separateBuySellOrders,
sortAndLimitOffers,
} from '../sugar/getOrderbook'
import { dropsToXrp, hashes, isValidClassicAddress } from '../utils'
import { decode, dropsToXrp, hashes, isValidClassicAddress } from '../utils'
import { Wallet } from '../Wallet'
import {
type FaucetRequestBody,
Expand Down Expand Up @@ -764,6 +766,70 @@ class Client extends EventEmitter<EventTypes> {
return submitRequest(this, signedTx, opts?.failHard)
}

/**
* Simulates an unsigned transaction.
* Steps performed on a transaction:
* 1. Autofill.
* 2. Sign & Encode.
* 3. Submit.
*
* @category Core
*
* @param transaction - A transaction to autofill, sign & encode, and submit.
* @param opts - (Optional) Options used to sign and submit a transaction.
* @param opts.binary - If true, return the metadata in a binary encoding.
*
* @returns A promise that contains SimulateResponse.
* @throws RippledError if the simulate request fails.
*/
public async simulate(
transaction: SubmittableTransaction | string,
opts?: {
// If true, return the binary-encoded representation of the results.
binary?: boolean
},
): Promise<SimulateResponse> {
// verify that the transaction isn't signed
const decodedTx =
typeof transaction === 'string'
? // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- needed for typing
(decode(transaction) as unknown as SubmittableTransaction)
: transaction
if (typeof decodedTx === 'string') {
throw new ValidationError(
'Provided transaction is not a valid transaction.',
)
}
if (decodedTx.TxnSignature !== '' && decodedTx.TxnSignature != null) {
throw new ValidationError('Transaction must not be signed.')
}
if (
decodedTx.Signers?.some(
(signer) =>
signer.Signer.TxnSignature !== '' &&
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- needed for JS
signer.Signer.TxnSignature != null,
)
) {
throw new ValidationError('Transaction must not be signed.')
}

setValidAddresses(decodedTx)
setTransactionFlagsToNumber(decodedTx)

if (decodedTx.NetworkID == null) {
decodedTx.NetworkID = txNeedsNetworkID(this) ? this.networkID : undefined
}

// send request
const binary = opts?.binary ?? false
const request: SimulateRequest =
typeof transaction === 'string'
? { command: 'simulate', tx_blob: transaction, binary }
: { command: 'simulate', tx_json: transaction, binary }
return this.request(request)
}

/**
* Asynchronously submits a transaction and verifies that it has been included in a
* validated ledger (or has errored/will not be included for some reason).
Expand Down
2 changes: 2 additions & 0 deletions packages/xrpl/src/models/methods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ type Request =
| LedgerDataRequest
| LedgerEntryRequest
// transaction methods
| SimulateRequest
| SubmitRequest
| SubmitMultisignedRequest
| TransactionEntryRequest
Expand Down Expand Up @@ -269,6 +270,7 @@ type Response<Version extends APIVersion = typeof DEFAULT_API_VERSION> =
| LedgerDataResponse
| LedgerEntryResponse
// transaction methods
| SimulateResponse
| SubmitResponse
| SubmitMultisignedVersionResponseMap<Version>
| TransactionEntryResponse
Expand Down
28 changes: 12 additions & 16 deletions packages/xrpl/src/models/methods/simulate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,8 @@ import { BaseRequest, BaseResponse } from './baseMethod'
*
* @category Requests
*/
export type SimulateRequest = SimulateBinaryRequest | SimulateJsonRequest

export type SimulateBinaryRequest = BaseRequest & {
command: 'simulate'

binary: true
} & (
export type SimulateRequest = SimulateRequestBase &
(
| {
tx_blob: string
}
Expand All @@ -27,18 +22,19 @@ export type SimulateBinaryRequest = BaseRequest & {
}
)

export type SimulateJsonRequest = BaseRequest & {
export interface SimulateRequestBase extends BaseRequest {
command: 'simulate'

binary?: boolean
}

export type SimulateBinaryRequest = SimulateRequest & {
binary: true
}

export type SimulateJsonRequest = SimulateRequest & {
binary?: false
} & (
| {
tx_blob: string
}
| {
tx_json: Transaction
}
)
}

export type SimulateResponse = SimulateBinaryResponse | SimulateJsonResponse

Expand Down
5 changes: 2 additions & 3 deletions packages/xrpl/src/sugar/submit.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { decode, encode } from 'ripple-binary-codec'

import type {
Client,
SubmitRequest,
Expand All @@ -12,6 +10,7 @@ import { ValidationError, XrplError } from '../errors'
import { Signer } from '../models/common'
import { TxResponse } from '../models/methods'
import { BaseTransaction } from '../models/transactions/common'
import { decode, encode } from '../utils'

/** Approximate time for a ledger to close, in milliseconds */
const LEDGER_CLOSE_TIME = 1000
Expand Down Expand Up @@ -52,7 +51,7 @@ export async function submitRequest(
failHard = false,
): Promise<SubmitResponse> {
if (!isSigned(signedTransaction)) {
throw new ValidationError('Transaction must be signed')
throw new ValidationError('Transaction must be signed.')
}

const signedTxEncoded =
Expand Down

0 comments on commit 78b1c20

Please sign in to comment.