mirror of
				https://github.com/Xahau/xahau.js.git
				synced 2025-11-04 04:55:48 +00:00 
			
		
		
		
	test: add integration tests for sidechain transactions (#2301)
* add XChainCreateBridge integration test * add XChainCreateClaimID integration test * add XChainCommit integration test * add XChainAccountCreateCommit integration test * simplify tests * add XChainModifyBridge integration test * add XChainAddAccountCreateAttestation integration test * add XChainAddClaimAttestation integration test * improve SignerListSet integration test * rename variable to match * add XChainClaim integration test * clean up * add IOU attestation test * fix integration tests issues * minor refactors * fix bug * [WIP] switch to one bridge for all integration tests * clean up * fix tests * fix + clean up tests
This commit is contained in:
		@@ -67,20 +67,20 @@ class XChainBridge extends SerializedType {
 | 
			
		||||
      return value
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isXChainBridgeObject(value)) {
 | 
			
		||||
      const bytes: Array<Buffer> = []
 | 
			
		||||
      this.TYPE_ORDER.forEach((item) => {
 | 
			
		||||
        const { name, type } = item
 | 
			
		||||
        if (type === AccountID) {
 | 
			
		||||
          bytes.push(Buffer.from([0x14]))
 | 
			
		||||
        }
 | 
			
		||||
        const object = type.from(value[name])
 | 
			
		||||
        bytes.push(object.toBytes())
 | 
			
		||||
      })
 | 
			
		||||
      return new XChainBridge(Buffer.concat(bytes))
 | 
			
		||||
    if (!isXChainBridgeObject(value)) {
 | 
			
		||||
      throw new Error('Invalid type to construct an XChainBridge')
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    throw new Error('Invalid type to construct an XChainBridge')
 | 
			
		||||
    const bytes: Array<Buffer> = []
 | 
			
		||||
    this.TYPE_ORDER.forEach((item) => {
 | 
			
		||||
      const { name, type } = item
 | 
			
		||||
      if (type === AccountID) {
 | 
			
		||||
        bytes.push(Buffer.from([0x14]))
 | 
			
		||||
      }
 | 
			
		||||
      const object = type.from(value[name])
 | 
			
		||||
      bytes.push(object.toBytes())
 | 
			
		||||
    })
 | 
			
		||||
    return new XChainBridge(Buffer.concat(bytes))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
 
 | 
			
		||||
@@ -22,13 +22,6 @@ export default interface Bridge extends BaseLedgerEntry, HasPreviousTxnID {
 | 
			
		||||
   */
 | 
			
		||||
  SignatureReward: Amount
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The minimum amount, in XRP, required for an {@link XChainAccountCreateCommit}
 | 
			
		||||
   * transaction. If this isn't present, the {@link XChainAccountCreateCommit}
 | 
			
		||||
   * transaction will fail. This field can only be present on XRP-XRP bridges.
 | 
			
		||||
   */
 | 
			
		||||
  MinAccountCreateAmount?: string
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The door accounts and assets of the bridge this object correlates to.
 | 
			
		||||
   */
 | 
			
		||||
@@ -58,6 +51,13 @@ export default interface Bridge extends BaseLedgerEntry, HasPreviousTxnID {
 | 
			
		||||
   */
 | 
			
		||||
  XChainAccountClaimCount: string
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * The minimum amount, in XRP, required for an {@link XChainAccountCreateCommit}
 | 
			
		||||
   * transaction. If this isn't present, the {@link XChainAccountCreateCommit}
 | 
			
		||||
   * transaction will fail. This field can only be present on XRP-XRP bridges.
 | 
			
		||||
   */
 | 
			
		||||
  MinAccountCreateAmount?: string
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * A bit-map of boolean flags. No flags are defined for Bridges, so this value
 | 
			
		||||
   * is always 0.
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ import {
 | 
			
		||||
 * The XChainAccountCreateCommit transaction creates a new account on one of the
 | 
			
		||||
 * chains a bridge connects, which serves as the bridge entrance for that chain.
 | 
			
		||||
 *
 | 
			
		||||
 * Warning: This transaction should only be executed if the witness attestations
 | 
			
		||||
 * WARNING: This transaction should only be executed if the witness attestations
 | 
			
		||||
 * will be reliably delivered to the destination chain. If the signatures aren't
 | 
			
		||||
 * delivered, then account creation will be blocked until attestations are received.
 | 
			
		||||
 * This can be used maliciously; to disable this transaction on XRP-XRP bridges,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ async function generate_faucet_wallet_and_fund_again(
 | 
			
		||||
    faucetPath,
 | 
			
		||||
    usageContext: 'integration-test',
 | 
			
		||||
  })
 | 
			
		||||
  assert.notEqual(wallet, undefined)
 | 
			
		||||
  assert.notStrictEqual(wallet, undefined)
 | 
			
		||||
  assert(isValidClassicAddress(wallet.classicAddress))
 | 
			
		||||
  assert(isValidXAddress(wallet.getXAddress()))
 | 
			
		||||
 | 
			
		||||
@@ -103,7 +103,7 @@ describe('fundWallet', function () {
 | 
			
		||||
        usageContext: 'integration-test',
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      assert.notEqual(wallet, undefined)
 | 
			
		||||
      assert.notStrictEqual(wallet, undefined)
 | 
			
		||||
      assert(isValidClassicAddress(wallet.classicAddress))
 | 
			
		||||
      assert(isValidXAddress(wallet.getXAddress()))
 | 
			
		||||
 | 
			
		||||
@@ -137,7 +137,7 @@ describe('fundWallet', function () {
 | 
			
		||||
        usageContext: 'integration-test',
 | 
			
		||||
      })
 | 
			
		||||
      assert.equal(balance, '2000')
 | 
			
		||||
      assert.notEqual(wallet, undefined)
 | 
			
		||||
      assert.notStrictEqual(wallet, undefined)
 | 
			
		||||
      assert(isValidClassicAddress(wallet.classicAddress))
 | 
			
		||||
      assert(isValidXAddress(wallet.getXAddress()))
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,14 @@ export * from './transactions/paymentChannelCreate.test'
 | 
			
		||||
export * from './transactions/paymentChannelFund.test'
 | 
			
		||||
export * from './transactions/signerListSet.test'
 | 
			
		||||
export * from './transactions/trustSet.test'
 | 
			
		||||
export * from './transactions/xchainAccountCreateCommit.test'
 | 
			
		||||
export * from './transactions/xchainAddAccountCreateAttestation.test'
 | 
			
		||||
export * from './transactions/xchainAddClaimAttestation.test'
 | 
			
		||||
export * from './transactions/xchainClaim.test'
 | 
			
		||||
export * from './transactions/xchainCreateBridge.test'
 | 
			
		||||
export * from './transactions/xchainCreateClaimID.test'
 | 
			
		||||
export * from './transactions/xchainCommit.test'
 | 
			
		||||
export * from './transactions/xchainModifyBridge.test'
 | 
			
		||||
 | 
			
		||||
// Requests
 | 
			
		||||
export * from './requests/accountChannels.test'
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,26 @@
 | 
			
		||||
import { Client, Wallet } from '../../src'
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  Client,
 | 
			
		||||
  SignerListSet,
 | 
			
		||||
  Wallet,
 | 
			
		||||
  XChainBridge,
 | 
			
		||||
  XChainCreateBridge,
 | 
			
		||||
} from '../../src'
 | 
			
		||||
 | 
			
		||||
import serverUrl from './serverUrl'
 | 
			
		||||
import { fundAccount } from './utils'
 | 
			
		||||
import {
 | 
			
		||||
  GENESIS_ACCOUNT,
 | 
			
		||||
  fundAccount,
 | 
			
		||||
  generateFundedWallet,
 | 
			
		||||
  testTransaction,
 | 
			
		||||
} from './utils'
 | 
			
		||||
 | 
			
		||||
interface TestBridge {
 | 
			
		||||
  xchainBridge: XChainBridge
 | 
			
		||||
  witness: Wallet
 | 
			
		||||
  signatureReward: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface XrplIntegrationTestContext {
 | 
			
		||||
  client: Client
 | 
			
		||||
@@ -32,15 +51,86 @@ async function connectWithRetry(client: Client, tries = 0): Promise<void> {
 | 
			
		||||
export async function setupClient(
 | 
			
		||||
  server = serverUrl,
 | 
			
		||||
): Promise<XrplIntegrationTestContext> {
 | 
			
		||||
  const context: XrplIntegrationTestContext = {
 | 
			
		||||
    client: new Client(server, { timeout: 200000 }),
 | 
			
		||||
    wallet: Wallet.generate(),
 | 
			
		||||
  }
 | 
			
		||||
  return connectWithRetry(context.client).then(async () => {
 | 
			
		||||
    await fundAccount(context.client, context.wallet, {
 | 
			
		||||
  const client = new Client(server, { timeout: 200000 })
 | 
			
		||||
  const wallet = Wallet.generate()
 | 
			
		||||
  return connectWithRetry(client).then(async () => {
 | 
			
		||||
    await fundAccount(client, wallet, {
 | 
			
		||||
      count: 20,
 | 
			
		||||
      delayMs: 1000,
 | 
			
		||||
    })
 | 
			
		||||
    const context: XrplIntegrationTestContext = {
 | 
			
		||||
      client,
 | 
			
		||||
      wallet,
 | 
			
		||||
    }
 | 
			
		||||
    return context
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function setupBridge(client: Client): Promise<TestBridge> {
 | 
			
		||||
  const doorAccount = await generateFundedWallet(client)
 | 
			
		||||
  const signatureReward = '200'
 | 
			
		||||
  const xchainBridge: XChainBridge = {
 | 
			
		||||
    LockingChainDoor: doorAccount.classicAddress,
 | 
			
		||||
    LockingChainIssue: { currency: 'XRP' },
 | 
			
		||||
    IssuingChainDoor: GENESIS_ACCOUNT,
 | 
			
		||||
    IssuingChainIssue: { currency: 'XRP' },
 | 
			
		||||
  }
 | 
			
		||||
  const setupTx: XChainCreateBridge = {
 | 
			
		||||
    TransactionType: 'XChainCreateBridge',
 | 
			
		||||
    Account: doorAccount.classicAddress,
 | 
			
		||||
    XChainBridge: xchainBridge,
 | 
			
		||||
    SignatureReward: signatureReward,
 | 
			
		||||
    MinAccountCreateAmount: '10000000',
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  await testTransaction(client, setupTx, doorAccount)
 | 
			
		||||
 | 
			
		||||
  // confirm that the transaction actually went through
 | 
			
		||||
  const accountObjectsResponse = await client.request({
 | 
			
		||||
    command: 'account_objects',
 | 
			
		||||
    account: doorAccount.classicAddress,
 | 
			
		||||
    type: 'bridge',
 | 
			
		||||
  })
 | 
			
		||||
  assert.lengthOf(
 | 
			
		||||
    accountObjectsResponse.result.account_objects,
 | 
			
		||||
    1,
 | 
			
		||||
    'Should be exactly one bridge owned by the account',
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  const witnessWallet = await generateFundedWallet(client)
 | 
			
		||||
 | 
			
		||||
  const signerTx: SignerListSet = {
 | 
			
		||||
    TransactionType: 'SignerListSet',
 | 
			
		||||
    Account: doorAccount.classicAddress,
 | 
			
		||||
    SignerEntries: [
 | 
			
		||||
      {
 | 
			
		||||
        SignerEntry: {
 | 
			
		||||
          Account: witnessWallet.classicAddress,
 | 
			
		||||
          SignerWeight: 1,
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    ],
 | 
			
		||||
    SignerQuorum: 1,
 | 
			
		||||
  }
 | 
			
		||||
  await testTransaction(client, signerTx, doorAccount)
 | 
			
		||||
 | 
			
		||||
  const signerAccountInfoResponse = await client.request({
 | 
			
		||||
    command: 'account_info',
 | 
			
		||||
    account: doorAccount.classicAddress,
 | 
			
		||||
    signer_lists: true,
 | 
			
		||||
  })
 | 
			
		||||
  const signerListInfo =
 | 
			
		||||
    signerAccountInfoResponse.result.account_data.signer_lists?.[0]
 | 
			
		||||
  assert.deepEqual(
 | 
			
		||||
    signerListInfo?.SignerEntries,
 | 
			
		||||
    signerTx.SignerEntries,
 | 
			
		||||
    'SignerEntries were not set properly',
 | 
			
		||||
  )
 | 
			
		||||
  assert.equal(
 | 
			
		||||
    signerListInfo?.SignerQuorum,
 | 
			
		||||
    signerTx.SignerQuorum,
 | 
			
		||||
    'SignerQuorum was not set properly',
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  return { xchainBridge, witness: witnessWallet, signatureReward }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { SignerListSet } from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
@@ -42,6 +44,24 @@ describe('SignerListSet', function () {
 | 
			
		||||
        SignerQuorum: 2,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      const accountInfoResponse = await testContext.client.request({
 | 
			
		||||
        command: 'account_info',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        signer_lists: true,
 | 
			
		||||
      })
 | 
			
		||||
      const signerListInfo =
 | 
			
		||||
        accountInfoResponse.result.account_data.signer_lists?.[0]
 | 
			
		||||
      assert.deepEqual(
 | 
			
		||||
        signerListInfo?.SignerEntries,
 | 
			
		||||
        tx.SignerEntries,
 | 
			
		||||
        'SignerEntries were not set properly',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        signerListInfo?.SignerQuorum,
 | 
			
		||||
        tx.SignerQuorum,
 | 
			
		||||
        'SignerQuorum was not set properly',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,64 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { XChainAccountCreateCommit, Wallet } from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
  setupBridge,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { generateFundedWallet, getXRPBalance, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainAccountCreateCommit', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge, signatureReward } = await setupBridge(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
      )
 | 
			
		||||
      const initialBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, xchainBridge.LockingChainDoor),
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      // actually test XChainAccountCreateCommit
 | 
			
		||||
      const wallet2 = await generateFundedWallet(testContext.client)
 | 
			
		||||
      const destination = Wallet.generate()
 | 
			
		||||
      const amount = 10000000
 | 
			
		||||
      const tx: XChainAccountCreateCommit = {
 | 
			
		||||
        TransactionType: 'XChainAccountCreateCommit',
 | 
			
		||||
        Account: wallet2.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        Amount: amount.toString(),
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, tx, wallet2)
 | 
			
		||||
 | 
			
		||||
      const accountInfoResponse2 = await testContext.client.request({
 | 
			
		||||
        command: 'account_info',
 | 
			
		||||
        account: xchainBridge.LockingChainDoor,
 | 
			
		||||
      })
 | 
			
		||||
      const finalBalance = Number(
 | 
			
		||||
        accountInfoResponse2.result.account_data.Balance,
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        finalBalance,
 | 
			
		||||
        initialBalance + amount + Number(signatureReward),
 | 
			
		||||
        "The bridge door's balance should go up by the amount committed",
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
import { encode } from 'ripple-binary-codec'
 | 
			
		||||
import { sign } from 'ripple-keypairs'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  Wallet,
 | 
			
		||||
  XChainAddAccountCreateAttestation,
 | 
			
		||||
  xrpToDrops,
 | 
			
		||||
} from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupBridge,
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateBridge', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge, witness, signatureReward } = await setupBridge(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
      )
 | 
			
		||||
      const destination = Wallet.generate()
 | 
			
		||||
      const otherChainSource = Wallet.generate()
 | 
			
		||||
 | 
			
		||||
      const attestationToSign = {
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: xrpToDrops(300),
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainAccountCreateCount: 1,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
      }
 | 
			
		||||
      const encodedAttestation = encode(attestationToSign)
 | 
			
		||||
      const attestationSignature = sign(encodedAttestation, witness.privateKey)
 | 
			
		||||
 | 
			
		||||
      const tx: XChainAddAccountCreateAttestation = {
 | 
			
		||||
        TransactionType: 'XChainAddAccountCreateAttestation',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: xrpToDrops(300),
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainAccountCreateCount: 1,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        PublicKey: witness.publicKey,
 | 
			
		||||
        Signature: attestationSignature,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        AttestationSignerAccount: witness.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      // should not throw
 | 
			
		||||
      await testContext.client.request({
 | 
			
		||||
        command: 'account_info',
 | 
			
		||||
        account: destination.classicAddress,
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,274 @@
 | 
			
		||||
/* eslint-disable max-statements -- necessary because transfers require a lot of steps */
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
import { encode } from 'ripple-binary-codec'
 | 
			
		||||
import { sign } from 'ripple-keypairs'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  AccountSet,
 | 
			
		||||
  AccountSetAsfFlags,
 | 
			
		||||
  IssuedCurrency,
 | 
			
		||||
  IssuedCurrencyAmount,
 | 
			
		||||
  SignerListSet,
 | 
			
		||||
  TrustSet,
 | 
			
		||||
  Wallet,
 | 
			
		||||
  XChainAddClaimAttestation,
 | 
			
		||||
  XChainBridge,
 | 
			
		||||
  XChainCreateBridge,
 | 
			
		||||
  XChainCreateClaimID,
 | 
			
		||||
  xrpToDrops,
 | 
			
		||||
} from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupBridge,
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import {
 | 
			
		||||
  generateFundedWallet,
 | 
			
		||||
  getIOUBalance,
 | 
			
		||||
  getXRPBalance,
 | 
			
		||||
  testTransaction,
 | 
			
		||||
} from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateBridge', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge, witness, signatureReward } = await setupBridge(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
      )
 | 
			
		||||
      const otherChainSource = Wallet.generate()
 | 
			
		||||
      const amount = xrpToDrops(10)
 | 
			
		||||
 | 
			
		||||
      const claimIdTx: XChainCreateClaimID = {
 | 
			
		||||
        TransactionType: 'XChainCreateClaimID',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, claimIdTx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      const initialBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, testContext.wallet),
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const attestationToSign = {
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Destination: testContext.wallet.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      const encodedAttestation = encode(attestationToSign)
 | 
			
		||||
      const attestationSignature = sign(encodedAttestation, witness.privateKey)
 | 
			
		||||
 | 
			
		||||
      const tx: XChainAddClaimAttestation = {
 | 
			
		||||
        TransactionType: 'XChainAddClaimAttestation',
 | 
			
		||||
        Account: witness.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Destination: testContext.wallet.classicAddress,
 | 
			
		||||
        PublicKey: witness.publicKey,
 | 
			
		||||
        Signature: attestationSignature,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        AttestationSignerAccount: witness.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, witness)
 | 
			
		||||
 | 
			
		||||
      const finalBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, testContext.wallet),
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        finalBalance,
 | 
			
		||||
        initialBalance + Number(amount) - Number(signatureReward),
 | 
			
		||||
        'The destination balance should go up by the amount transferred',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'IOU',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const witness = await generateFundedWallet(testContext.client)
 | 
			
		||||
      // we are on the "issuing chain" for this test
 | 
			
		||||
      const lockingDoor = Wallet.generate()
 | 
			
		||||
      const issuer = Wallet.generate()
 | 
			
		||||
 | 
			
		||||
      // set default rippling
 | 
			
		||||
      const defaultRipplingTx: AccountSet = {
 | 
			
		||||
        TransactionType: 'AccountSet',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        SetFlag: AccountSetAsfFlags.asfDefaultRipple,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
        defaultRipplingTx,
 | 
			
		||||
        testContext.wallet,
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const destination = await generateFundedWallet(testContext.client)
 | 
			
		||||
 | 
			
		||||
      const trustlineTx: TrustSet = {
 | 
			
		||||
        TransactionType: 'TrustSet',
 | 
			
		||||
        Account: destination.classicAddress,
 | 
			
		||||
        LimitAmount: {
 | 
			
		||||
          currency: 'USD',
 | 
			
		||||
          issuer: testContext.wallet.classicAddress,
 | 
			
		||||
          value: '1000000000',
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, trustlineTx, destination)
 | 
			
		||||
 | 
			
		||||
      const signatureReward = '200'
 | 
			
		||||
      const xchainBridge: XChainBridge = {
 | 
			
		||||
        LockingChainDoor: lockingDoor.classicAddress,
 | 
			
		||||
        LockingChainIssue: {
 | 
			
		||||
          currency: 'USD',
 | 
			
		||||
          issuer: issuer.classicAddress,
 | 
			
		||||
        },
 | 
			
		||||
        IssuingChainDoor: testContext.wallet.classicAddress,
 | 
			
		||||
        IssuingChainIssue: {
 | 
			
		||||
          currency: 'USD',
 | 
			
		||||
          issuer: testContext.wallet.classicAddress,
 | 
			
		||||
        },
 | 
			
		||||
      }
 | 
			
		||||
      const setupTx: XChainCreateBridge = {
 | 
			
		||||
        TransactionType: 'XChainCreateBridge',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, setupTx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      // confirm that the transaction actually went through
 | 
			
		||||
      const accountObjectsResponse = await testContext.client.request({
 | 
			
		||||
        command: 'account_objects',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        type: 'bridge',
 | 
			
		||||
      })
 | 
			
		||||
      assert.lengthOf(
 | 
			
		||||
        accountObjectsResponse.result.account_objects,
 | 
			
		||||
        1,
 | 
			
		||||
        'Should be exactly one bridge owned by the account',
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const signerTx: SignerListSet = {
 | 
			
		||||
        TransactionType: 'SignerListSet',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        SignerEntries: [
 | 
			
		||||
          {
 | 
			
		||||
            SignerEntry: {
 | 
			
		||||
              Account: witness.classicAddress,
 | 
			
		||||
              SignerWeight: 1,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
        ],
 | 
			
		||||
        SignerQuorum: 1,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, signerTx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      const signerAccountInfoResponse = await testContext.client.request({
 | 
			
		||||
        command: 'account_info',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        signer_lists: true,
 | 
			
		||||
      })
 | 
			
		||||
      const signerListInfo =
 | 
			
		||||
        signerAccountInfoResponse.result.account_data.signer_lists?.[0]
 | 
			
		||||
      assert.deepEqual(
 | 
			
		||||
        signerListInfo?.SignerEntries,
 | 
			
		||||
        signerTx.SignerEntries,
 | 
			
		||||
        'SignerEntries were not set properly',
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        signerListInfo?.SignerQuorum,
 | 
			
		||||
        signerTx.SignerQuorum,
 | 
			
		||||
        'SignerQuorum was not set properly',
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const otherChainSource = Wallet.generate()
 | 
			
		||||
      const amount: IssuedCurrencyAmount = {
 | 
			
		||||
        currency: 'USD',
 | 
			
		||||
        issuer: issuer.classicAddress,
 | 
			
		||||
        value: '10',
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const claimIdTx: XChainCreateClaimID = {
 | 
			
		||||
        TransactionType: 'XChainCreateClaimID',
 | 
			
		||||
        Account: destination.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, claimIdTx, destination)
 | 
			
		||||
 | 
			
		||||
      const initialBalance = Number(
 | 
			
		||||
        await getIOUBalance(
 | 
			
		||||
          testContext.client,
 | 
			
		||||
          destination,
 | 
			
		||||
          xchainBridge.IssuingChainIssue as IssuedCurrency,
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const attestationToSign = {
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        WasLockingChainSend: 1,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      const encodedAttestation = encode(attestationToSign)
 | 
			
		||||
      const attestationSignature = sign(encodedAttestation, witness.privateKey)
 | 
			
		||||
 | 
			
		||||
      const tx: XChainAddClaimAttestation = {
 | 
			
		||||
        TransactionType: 'XChainAddClaimAttestation',
 | 
			
		||||
        Account: witness.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        WasLockingChainSend: 1,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
        PublicKey: witness.publicKey,
 | 
			
		||||
        Signature: attestationSignature,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        AttestationSignerAccount: witness.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, witness)
 | 
			
		||||
 | 
			
		||||
      const finalBalance = Number(
 | 
			
		||||
        await getIOUBalance(
 | 
			
		||||
          testContext.client,
 | 
			
		||||
          destination,
 | 
			
		||||
          xchainBridge.IssuingChainIssue as IssuedCurrency,
 | 
			
		||||
        ),
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        finalBalance,
 | 
			
		||||
        initialBalance + Number(amount.value),
 | 
			
		||||
        'The destination balance should go up by the amount transferred',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										112
									
								
								packages/xrpl/test/integration/transactions/xchainClaim.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								packages/xrpl/test/integration/transactions/xchainClaim.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,112 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
import { encode } from 'ripple-binary-codec'
 | 
			
		||||
import { sign } from 'ripple-keypairs'
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
  Wallet,
 | 
			
		||||
  XChainAddClaimAttestation,
 | 
			
		||||
  XChainClaim,
 | 
			
		||||
  XChainCreateClaimID,
 | 
			
		||||
  xrpToDrops,
 | 
			
		||||
} from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupBridge,
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { generateFundedWallet, getXRPBalance, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateBridge', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge, witness, signatureReward } = await setupBridge(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const destination = await generateFundedWallet(testContext.client)
 | 
			
		||||
      const otherChainSource = Wallet.generate()
 | 
			
		||||
      const amount = xrpToDrops(10)
 | 
			
		||||
 | 
			
		||||
      const claimIdTx: XChainCreateClaimID = {
 | 
			
		||||
        TransactionType: 'XChainCreateClaimID',
 | 
			
		||||
        Account: destination.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, claimIdTx, destination)
 | 
			
		||||
 | 
			
		||||
      const initialBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, destination),
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const attestationToSign = {
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
      }
 | 
			
		||||
      const encodedAttestation = encode(attestationToSign)
 | 
			
		||||
      const attestationSignature = sign(encodedAttestation, witness.privateKey)
 | 
			
		||||
 | 
			
		||||
      const claimTx: XChainAddClaimAttestation = {
 | 
			
		||||
        TransactionType: 'XChainAddClaimAttestation',
 | 
			
		||||
        Account: witness.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
        WasLockingChainSend: 0,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        PublicKey: witness.publicKey,
 | 
			
		||||
        Signature: attestationSignature,
 | 
			
		||||
        AttestationRewardAccount: witness.classicAddress,
 | 
			
		||||
        AttestationSignerAccount: witness.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, claimTx, witness)
 | 
			
		||||
 | 
			
		||||
      const intermediateBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, destination),
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        initialBalance,
 | 
			
		||||
        intermediateBalance,
 | 
			
		||||
        "The destination's balance should not change yet",
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const tx: XChainClaim = {
 | 
			
		||||
        TransactionType: 'XChainClaim',
 | 
			
		||||
        Account: destination.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        Destination: destination.classicAddress,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Amount: amount,
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, destination)
 | 
			
		||||
 | 
			
		||||
      const finalBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, destination),
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        finalBalance,
 | 
			
		||||
        initialBalance + Number(amount) - Number(signatureReward) - 12,
 | 
			
		||||
        "The destination's balance should not change yet",
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { XChainCommit } from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupBridge,
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { generateFundedWallet, getXRPBalance, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCommit', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge } = await setupBridge(testContext.client)
 | 
			
		||||
 | 
			
		||||
      const initialBalance = Number(
 | 
			
		||||
        await getXRPBalance(testContext.client, xchainBridge.LockingChainDoor),
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      // actually test XChainCommit
 | 
			
		||||
      const wallet2 = await generateFundedWallet(testContext.client)
 | 
			
		||||
      const amount = 10000000
 | 
			
		||||
      const tx: XChainCommit = {
 | 
			
		||||
        TransactionType: 'XChainCommit',
 | 
			
		||||
        Account: wallet2.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        XChainClaimID: 1,
 | 
			
		||||
        Amount: amount.toString(),
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, tx, wallet2)
 | 
			
		||||
 | 
			
		||||
      const accountInfoResponse2 = await testContext.client.request({
 | 
			
		||||
        command: 'account_info',
 | 
			
		||||
        account: xchainBridge.LockingChainDoor,
 | 
			
		||||
      })
 | 
			
		||||
      const finalBalance = Number(
 | 
			
		||||
        accountInfoResponse2.result.account_data.Balance,
 | 
			
		||||
      )
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        initialBalance + amount,
 | 
			
		||||
        finalBalance,
 | 
			
		||||
        "The bridge door's balance should go up by the amount committed",
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,55 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { XChainCreateBridge } from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { GENESIS_ACCOUNT, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateBridge', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const tx: XChainCreateBridge = {
 | 
			
		||||
        TransactionType: 'XChainCreateBridge',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: {
 | 
			
		||||
          LockingChainDoor: testContext.wallet.classicAddress,
 | 
			
		||||
          LockingChainIssue: { currency: 'XRP' },
 | 
			
		||||
          IssuingChainDoor: GENESIS_ACCOUNT,
 | 
			
		||||
          IssuingChainIssue: { currency: 'XRP' },
 | 
			
		||||
        },
 | 
			
		||||
        SignatureReward: '200',
 | 
			
		||||
        MinAccountCreateAmount: '10000000',
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, tx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      // confirm that the transaction actually went through
 | 
			
		||||
      const accountObjectsResponse = await testContext.client.request({
 | 
			
		||||
        command: 'account_objects',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        type: 'bridge',
 | 
			
		||||
      })
 | 
			
		||||
      assert.lengthOf(
 | 
			
		||||
        accountObjectsResponse.result.account_objects,
 | 
			
		||||
        1,
 | 
			
		||||
        'Should be exactly one bridge owned by the account',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { XChainCreateClaimID, Wallet } from '../../../src'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupBridge,
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { generateFundedWallet, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateClaimID', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const { xchainBridge, signatureReward } = await setupBridge(
 | 
			
		||||
        testContext.client,
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      // actually test XChainCreateClaimID
 | 
			
		||||
      const wallet2 = await generateFundedWallet(testContext.client)
 | 
			
		||||
      const otherChainSource = Wallet.generate()
 | 
			
		||||
      const tx: XChainCreateClaimID = {
 | 
			
		||||
        TransactionType: 'XChainCreateClaimID',
 | 
			
		||||
        Account: wallet2.classicAddress,
 | 
			
		||||
        XChainBridge: xchainBridge,
 | 
			
		||||
        SignatureReward: signatureReward,
 | 
			
		||||
        OtherChainSource: otherChainSource.classicAddress,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, tx, wallet2)
 | 
			
		||||
 | 
			
		||||
      const accountObjectsResponse2 = await testContext.client.request({
 | 
			
		||||
        command: 'account_objects',
 | 
			
		||||
        account: wallet2.classicAddress,
 | 
			
		||||
        type: 'xchain_owned_claim_id',
 | 
			
		||||
      })
 | 
			
		||||
      assert.lengthOf(
 | 
			
		||||
        accountObjectsResponse2.result.account_objects,
 | 
			
		||||
        1,
 | 
			
		||||
        'Should be exactly one claim ID owned by the account',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -0,0 +1,95 @@
 | 
			
		||||
import { assert } from 'chai'
 | 
			
		||||
 | 
			
		||||
import { XChainCreateBridge, XChainModifyBridge } from '../../../src'
 | 
			
		||||
import { Bridge } from '../../../src/models/ledger'
 | 
			
		||||
import serverUrl from '../serverUrl'
 | 
			
		||||
import {
 | 
			
		||||
  setupClient,
 | 
			
		||||
  teardownClient,
 | 
			
		||||
  type XrplIntegrationTestContext,
 | 
			
		||||
} from '../setup'
 | 
			
		||||
import { GENESIS_ACCOUNT, testTransaction } from '../utils'
 | 
			
		||||
 | 
			
		||||
// how long before each test case times out
 | 
			
		||||
const TIMEOUT = 20000
 | 
			
		||||
 | 
			
		||||
describe('XChainCreateBridge', function () {
 | 
			
		||||
  let testContext: XrplIntegrationTestContext
 | 
			
		||||
 | 
			
		||||
  beforeEach(async () => {
 | 
			
		||||
    testContext = await setupClient(serverUrl)
 | 
			
		||||
  })
 | 
			
		||||
  afterEach(async () => teardownClient(testContext))
 | 
			
		||||
 | 
			
		||||
  it(
 | 
			
		||||
    'base',
 | 
			
		||||
    async () => {
 | 
			
		||||
      const setupTx: XChainCreateBridge = {
 | 
			
		||||
        TransactionType: 'XChainCreateBridge',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: {
 | 
			
		||||
          LockingChainDoor: testContext.wallet.classicAddress,
 | 
			
		||||
          LockingChainIssue: { currency: 'XRP' },
 | 
			
		||||
          IssuingChainDoor: GENESIS_ACCOUNT,
 | 
			
		||||
          IssuingChainIssue: { currency: 'XRP' },
 | 
			
		||||
        },
 | 
			
		||||
        SignatureReward: '200',
 | 
			
		||||
        MinAccountCreateAmount: '10000000',
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await testTransaction(testContext.client, setupTx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      // confirm that the transaction actually went through
 | 
			
		||||
      const accountObjectsResponse = await testContext.client.request({
 | 
			
		||||
        command: 'account_objects',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        type: 'bridge',
 | 
			
		||||
      })
 | 
			
		||||
      assert.lengthOf(
 | 
			
		||||
        accountObjectsResponse.result.account_objects,
 | 
			
		||||
        1,
 | 
			
		||||
        'Should be exactly one bridge owned by the account',
 | 
			
		||||
      )
 | 
			
		||||
      const initialBridge = accountObjectsResponse.result
 | 
			
		||||
        .account_objects[0] as unknown as Bridge
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        initialBridge.SignatureReward,
 | 
			
		||||
        '200',
 | 
			
		||||
        'Signature reward is incorrect',
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      const tx: XChainModifyBridge = {
 | 
			
		||||
        TransactionType: 'XChainModifyBridge',
 | 
			
		||||
        Account: testContext.wallet.classicAddress,
 | 
			
		||||
        XChainBridge: {
 | 
			
		||||
          LockingChainDoor: testContext.wallet.classicAddress,
 | 
			
		||||
          LockingChainIssue: { currency: 'XRP' },
 | 
			
		||||
          IssuingChainDoor: GENESIS_ACCOUNT,
 | 
			
		||||
          IssuingChainIssue: { currency: 'XRP' },
 | 
			
		||||
        },
 | 
			
		||||
        SignatureReward: '300',
 | 
			
		||||
      }
 | 
			
		||||
      await testTransaction(testContext.client, tx, testContext.wallet)
 | 
			
		||||
 | 
			
		||||
      // confirm that the transaction actually went through
 | 
			
		||||
      const accountObjectsResponse2 = await testContext.client.request({
 | 
			
		||||
        command: 'account_objects',
 | 
			
		||||
        account: testContext.wallet.classicAddress,
 | 
			
		||||
        type: 'bridge',
 | 
			
		||||
      })
 | 
			
		||||
      assert.lengthOf(
 | 
			
		||||
        accountObjectsResponse2.result.account_objects,
 | 
			
		||||
        1,
 | 
			
		||||
        'Should be exactly one bridge owned by the account',
 | 
			
		||||
      )
 | 
			
		||||
      const finalBridge = accountObjectsResponse2.result
 | 
			
		||||
        .account_objects[0] as unknown as Bridge
 | 
			
		||||
      assert.equal(
 | 
			
		||||
        finalBridge.SignatureReward,
 | 
			
		||||
        '300',
 | 
			
		||||
        'Signature reward was not modified',
 | 
			
		||||
      )
 | 
			
		||||
    },
 | 
			
		||||
    TIMEOUT,
 | 
			
		||||
  )
 | 
			
		||||
})
 | 
			
		||||
@@ -10,12 +10,14 @@ import {
 | 
			
		||||
  type SubmitResponse,
 | 
			
		||||
  TimeoutError,
 | 
			
		||||
  NotConnectedError,
 | 
			
		||||
  AccountLinesRequest,
 | 
			
		||||
  IssuedCurrency,
 | 
			
		||||
} from '../../src'
 | 
			
		||||
import { Payment, Transaction } from '../../src/models/transactions'
 | 
			
		||||
import { hashSignedTx } from '../../src/utils/hashes'
 | 
			
		||||
 | 
			
		||||
const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
 | 
			
		||||
const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
 | 
			
		||||
export const GENESIS_ACCOUNT = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'
 | 
			
		||||
const GENESIS_SECRET = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb'
 | 
			
		||||
 | 
			
		||||
export async function sendLedgerAccept(client: Client): Promise<unknown> {
 | 
			
		||||
  return client.connection.request({ command: 'ledger_accept' })
 | 
			
		||||
@@ -141,12 +143,12 @@ export async function fundAccount(
 | 
			
		||||
): Promise<SubmitResponse> {
 | 
			
		||||
  const payment: Payment = {
 | 
			
		||||
    TransactionType: 'Payment',
 | 
			
		||||
    Account: masterAccount,
 | 
			
		||||
    Account: GENESIS_ACCOUNT,
 | 
			
		||||
    Destination: wallet.classicAddress,
 | 
			
		||||
    // 2 times the amount needed for a new account (20 XRP)
 | 
			
		||||
    Amount: '400000000',
 | 
			
		||||
  }
 | 
			
		||||
  const wal = Wallet.fromSeed(masterSecret)
 | 
			
		||||
  const wal = Wallet.fromSeed(GENESIS_SECRET)
 | 
			
		||||
  const response = await submitTransaction({
 | 
			
		||||
    client,
 | 
			
		||||
    wallet: wal,
 | 
			
		||||
@@ -263,11 +265,13 @@ export async function testTransaction(
 | 
			
		||||
 | 
			
		||||
export async function getXRPBalance(
 | 
			
		||||
  client: Client,
 | 
			
		||||
  wallet: Wallet,
 | 
			
		||||
  account: string | Wallet,
 | 
			
		||||
): Promise<string> {
 | 
			
		||||
  const address: string =
 | 
			
		||||
    typeof account === 'string' ? account : account.classicAddress
 | 
			
		||||
  const request: AccountInfoRequest = {
 | 
			
		||||
    command: 'account_info',
 | 
			
		||||
    account: wallet.classicAddress,
 | 
			
		||||
    account: address,
 | 
			
		||||
  }
 | 
			
		||||
  return (await client.request(request)).result.account_data.Balance
 | 
			
		||||
}
 | 
			
		||||
@@ -338,3 +342,16 @@ export async function waitForAndForceProgressLedgerTime(
 | 
			
		||||
 | 
			
		||||
  throw new Error(`Ledger time not reached after ${retries} retries.`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getIOUBalance(
 | 
			
		||||
  client: Client,
 | 
			
		||||
  wallet: Wallet,
 | 
			
		||||
  currency: IssuedCurrency,
 | 
			
		||||
): Promise<string> {
 | 
			
		||||
  const request: AccountLinesRequest = {
 | 
			
		||||
    command: 'account_lines',
 | 
			
		||||
    account: wallet.classicAddress,
 | 
			
		||||
    peer: currency.issuer,
 | 
			
		||||
  }
 | 
			
		||||
  return (await client.request(request)).result.lines[0].balance
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user