Each transfer request must have its transfer details signed by a dedicated wallet. This should be the same wallet address that was configured as the signer when the contract was first deployed.
This is to ensure that none of the transfer details are changed at any point between the time they are sent to Loop and the time they are executed in the contract.
Transfer request are expected to be signed using the standard defined in EIP-712. See Securing with signatures for more information.
Parameters to sign
The 6 transfer parameters that need to be signed are:
Parameter
Description
These transfer parameters are sent to the smart contract along with the signature which are then validated on-chain against the signer address stored in the contract. If the on-chain validation of the parameters does not match the stored signer address during validation, the transfer for that order will fail and not be processed.
Example of how to sign transfer orders
constdomain= { name:"LoopVariableRatesContract", version:"1", chainId:137, verifyingContract:"0x26f1cB8611b15E6e3859d8Cf0ef294b7855d2135"};consttypes= { Transfer: [ { name:"invoiceId", type:"string" }, { name:"from", type:"address" }, { name:"to", type:"address" }, { name:"token", type:"address" }, { name:"amount", type:"uint256" }, { name:"usd", type:"bool" } ]};consttransfer1= { invoiceId:"ch_3LjpW92eZvKYlo2C0RYz8S7X",// e.g. a Stripe charge id from:"0xad4efce746f129a9df375af2ddcf9097531eb466", to:"0x0f2672BA12aed17BEe075F7AEabC24b98E3098Ca", token:"0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", amount:100000000,// e.g. 100 USDC usd:false};// Sign first transferconstsignature1=awaitsigner._signTypedData( domain, types, transfer1);// Construct first transfer order object with signature, entity ID assumed from API keyconsttransferOrder1= {...transfer1, signature1, itemId:"2a2f4ff3-6e26-4da3-a569-25f52492b112", billDate:"1664096943", networkId:137}consttransfer2= { invoiceId:"ch_1LlilL2eZvKYlo2ClNgXnUbd",// e.g. a Stripe charge id from:"0x02F84A56e4ebBA0F7840aab2664Ad1C8476B5Ed5", to:"0x0f2672BA12aed17BEe075F7AEabC24b98E3098Ca", token:"0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", amount:"10000000000",// e.g. 100 USD usd:true};// Sign second transferconstsignature2=awaitsigner._signTypedData( domain, types, transfer2);// Construct second transfer order object with signatureconsttransferOrder2= {...transfer2, signature2, itemId:"8695edec-c310-4ddc-b348-01087b2d730e", billDate:"1664272491", networkId:137, entityId:"3be77c6d-91e8-4507-81e9-b02be71d0f60"}// POST transfer orders to Loop APIconstres=awaitaxios.post("https://api.loopcrypto.xyz/api/v1/transfers", [ transferOrder1, transferOrder2 ], { headers: {"api-key":"eyJzaWduYXR1cmUiOiIweGU5Y2YwY2Y2YmM2NmV..." } });