# Submit Cross-chain Transactions

This tutorial explains how to create a test account on a locking chain (*Devent*), and transfer XRP to an issuing chain (*Sidechain-Devnet*), using a supported [client library](/ja/docs/references/client-libraries) to query and submit transactions. Witness servers are already set up to monitor the XRP-XRP bridge and submit attestations.

XChainBridge
## Prerequisites

- The locking and issuing chains are both up and running.
- The witness servers are up and running.
- Set up the XRP-XRP bridge.


## Steps

### 1. Connect to the locking chain (Devnet) and issuing chain (Sidechain-Devnet).


```javascript
const xrpl = require('xrpl')

const WS_URL_lockingchain = 'wss://s.devnet.rippletest.net:51233/' // Locking chain
const WS_URL_issuingchain = 'wss://example-sidechain.net:12345/' // Issuing chain

// Define the XChainBridge
const xchainbridge = {
  "LockingChainDoor": "rnQAXXWoFNN6PEqwqsdTngCtFPCrmfuqFJ", // Locking chain door account
  "LockingChainIssue": {
    "currency": "XRP"
  },
  "IssuingChainDoor": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", // Use the genesis address hardcoded in rippled
  "IssuingChainIssue": {
    "currency": "XRP"
  }
}

async function main() {
  // Define the network clients.
  const client_lockingchain = new xrpl.Client(WS_URL_lockingchain)
  await client_lockingchain.connect()

  const client_issuingchain = new xrpl.Client(WS_URL_issuingchain)
  await client_issuingchain.connect()

  // ... custom code goes here

  // Disconnect when done (If you omit this, Node.js won't end the process)
  await client_lockingchain.disconnect()
  await client_issuingchain.disconnect()
}

main()
```

### 2. Fund a wallet on Devnet and generate a wallet address for Sidechain-Devnet.


```javascript
  // Create a wallet and fund it using the XRP faucet on Devnet.
  const wallet_lockingchain = (await client_lockingchain.fundWallet()).wallet
  console.log(wallet_lockingchain.address)

  // Generate a wallet to create and fund on the issuing chain.
  const wallet_issuingchain = await xrpl.Wallet.generate()
  console.log(wallet_issuingchain.address)
```

### 3. Submit an `XChainAccountCreateCommit` transaction from the Devnet wallet.


```javascript
  const createwallet_issuingchain = await client_lockingchain.submitAndWait({
    "TransactionType": "XChainAccountCreateCommit",
    "Account": wallet_lockingchain.address,
    "Destination": wallet_issuingchain.address,
    "XChainBridge": xchainbridge,
    "SignatureReward": "100",
    "Amount": "5000000000"
  }, {autofill: true, wallet: wallet_lockingchain})
```

### 4. Create a claim ID with `XChainCreateClaimID`, using your account on the issuing chain.


```javascript
  const createclaim = await client_issuingchain.submitAndWait({
    "TransactionType": "XChainCreateClaimID",
    "Account": wallet_issuingchain.address,
    "OtherChainSource": wallet_lockingchain.address,
    "SignatureReward": "100",
    "XChainBridge": xchainbridge
  }, {autofill: true, wallet: wallet_issuingchain})
```

### 5. Retrieve the claim ID from the transaction metadata.


```javascript
  let metadata = createclaim.result.meta.AffectedNodes

  let claimnode = null;

  for (const item of metadata) {
    if (item.CreatedNode && item.CreatedNode.LedgerEntryType === 'XChainOwnedClaimID') {
      claimnode = item.CreatedNode
      break
    }
  }

  const claimID = claimnode.NewFields.XChainClaimID
```

### 6. Submit an `XChainCommit` transaction with the claim ID, using your account on the locking chain.

If you don't specify an "OtherChainDestination", the account that submitted the `XChainCreateClaimID` transaction needs to submit an `XChainClaim` transaction to claim the funds.


```javascript
  const xchaincommit = await client_lockingchain.submitAndWait({
    "TransactionType": "XChainCommit",
    "Account": wallet_lockingchain.address,
    "OtherChainDestination": wallet_issuingchain.address,
    "Amount": "10000",
    "XChainBridge": xchainbridge,
    "XChainClaimID": claimID
  }, {autofill: true, wallet: wallet_lockingchain})
```

When enough `XChainAddClaimAttestation` signatures are submitted by the witness servers to reach quorum, the funds are released on the issuing chain to the `OtherChainDestination`.