Skip to content

Latest commit

 

History

History
115 lines (81 loc) · 6.6 KB

File metadata and controls

115 lines (81 loc) · 6.6 KB
description
Sending ERC20 tokens from your Loopring L2 to another Loopring L2 address.

Transfer

EndPoint

POST api/v3/transfer

Header

FieldDescriptionExampleTypeRequired
X-API-KEYApiKey"HlkcGxbqBeaF76j4rvPaOasyfPwnkQ6B6DQ6THZWbvrGxzEdulXQvOKLrRWZLnN"Y
X-API-SIGECDSA Signature, pay attention the signature type,
sign the ecdsa hash
"0xccf0a141fce2dc5cbbd4f802c52220e9e2ce260e86704d6258603eb346eefe2d4a450005c362b223b2842d087f7065ea5eee0314531adf6a580fce64c25dca81c02"Y

Request

Query ParamDescriptionExample
exchangeexchangeAddress in exchange info
payerAddrpayer address
payerIdpayer account ID10110
payeeAddrpayee address
payeeIdpayee account ID10111,can set to 0 if dont have
tokentokenVolume,transfer tokenId and volume
maxFeetokenVolume from offchain fee
storageIdoffchainId of storage Id, sellTokenId is the transfer tokenId1
validUntilTimestamp for transfer to become invalid, seconds

normally current time + 2 months

eddsaSignatureeddsa signature
of the transfer eddsa hash
memo(Optional) memo
payPayeeUpdateAccount(Optional) transfer to pay payee updateAccount fee , true or false, default is falsetrue
counterFactualInfo(Optional) counterfactual Wallet Info, if it's a counterfactual wallet, need to pass the info

Response

FieldDescriptionExampleTypeRequired
hashThe hash identifier set by the user at the time of submission, can use this hash to get the transfer info"0x1d923ca7834dc90484fa2eb611f0f0bc7e741bb107007ebea19ba8caeab4f9d3"stringY
statusWhether the order was successfully submitted or not, please note, the user may query after a while to get the real process status, as most off-chain requests are asynchronously processed
Allowable : ['received', 'processing', 'processed', 'failed']
"received"stringY
isIdempotentIdempotent of submit transfer response, submit same transfer again idempotent will be true"false"booleanY

Model

TokenVolume

Wrapper object used to describe a token associated with a certain quantity.

FieldDescriptionExampleTypeRequired
tokenIdThe Loopring's token identifier.0integerY
volumeThe volume of the token"100000000000
0"
stringY

counterFactualInfo

Counterfactual wallet information.

FieldDescriptionExampleTypeRequired
walletFactoryCounterfactual wallet factory contract address"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd"stringY
walletOwnerCounterfactual wallet owner address, NOT the wallet address"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd"stringY
walletSaltSalt to generate address from owner & other related info"1"stringY

Compute ECDSA hash

const message = {
    from: data.payerAddr,
    to: data.payeeAddr,
    tokenID: data.token.tokenId,
    amount: data.token.volume,
    feeTokenID: data.maxFee.tokenId,
    maxFee: data.maxFee.volume,
    validUntil: data.validUntil,
    storageID: data.storageId,
  };
const typedData: EIP712TypedData = {
    types: {
      EIP712Domain: [
        { name: "name", type: "string" },
        { name: "version", type: "string" },
        { name: "chainId", type: "uint256" },
        { name: "verifyingContract", type: "address" },
      ],
      Transfer: [
        { name: "from", type: "address" },
        { name: "to", type: "address" },
        { name: "tokenID", type: "uint16" },
        { name: "amount", type: "uint96" },
        { name: "feeTokenID", type: "uint16" },
        { name: "maxFee", type: "uint96" },
        { name: "validUntil", type: "uint32" },
        { name: "storageID", type: "uint32" },
      ],
    },
    primaryType: "Transfer",
    domain: {
      name: "Loopring Protocol",
      version: "3.6.0",
      chainId: chainId,
      verifyingContract: data.exchange,
    },
    message: message,
  };

Compute EdDSA hash

const inputs = [
    new BN(ethUtil.toBuffer(request.exchange)).toString(),
    request.payerId,
    request.payeeId,
    request.token.tokenId,
    request.token.volume,
    request.maxFee.tokenId,
    request.maxFee.volume,
    new BN(ethUtil.toBuffer(request.payeeAddr)).toString(),
    0,
    0,
    request.validUntil,
    request.storageId,
];
const hasher = Poseidon.createHash(inputs.length + 1, 6, 53);
const hash = hasher(inputs).toString(10);