Loopring Dev Docs
  • Introduction
  • Endpoints
  • SDK
    • SDK Guides
    • Test Mock Data
      • Mock Account
      • Mock provider
      • Mock ERC20 Token Map
      • Mock AMM MAP
      • Mock EIP712 Typed Data
      • Mock Generate eddsaKey
  • Glossary
  • 🗳️Loopring Account
    • Introduction
    • SDK Guides
      • Setup a Loopring Account
      • Unlock Account (Login)
    • API References
      • Get Account info
        • Sample code
      • Update EddsaKey
        • Sample code
      • Get apiKey
        • Sample code
      • Update apiKey
        • Sample code
  • 🎨CounterFactual NFT
    • Introduction
      • Compute NFT Address API
      • When to deploy counterfactual NFT contracts?
    • SDK Guides
      • Deposit NFT
      • Create Collection
      • Mint Counterfactual NFT
      • Transfer NFT
      • Deploy NFT
      • Withdraw NFT
      • Trade NFT
        • Validate NFT Order
      • Meta & IPFS
    • API References
      • NFT Collection
        • Create collection
          • Sample code
        • Edit collection
          • Sample code
        • Delete collection
          • Sample code
        • List owned collections
          • Sample code
        • List user's NFTs under one collection
          • Sample code
        • List user's NFT balances group by Collection ID
          • Sample code
        • List all NFTs of a collection
          • Sample code
        • Get collection by Collection ID
          • Sample code
        • Get collections by contract address
          • Sample code
      • Get NFT Assets
        • Sample code
      • Get NFT Balances
        • Sample code
      • Mint NFT
        • Sample code
      • Transfer NFT
        • Sample code
      • Validate NFT Order
        • Sample code
      • Trade NFT
        • Sample code
      • Deploy NFT TokenAddress
        • Sample code
      • Withdraw NFT
        • Sample code
      • Get NFT Transactions
        • Sample code
      • Get NFT Trade History
        • Sample code
      • Get AvailableBroker
        • Sample code
      • Get NFT Info
        • Sample code
      • Get NFT Data
        • Sample code
      • Get NFT Holders
        • Sample code
  • 🪙ERC20 Tokens
    • Introduction
    • SDK Guides
      • Transfer ERC20
      • Withdraw ERC20
      • Deposit ERC20
      • Order ERC20
    • API References
      • Get Assets
        • Sample code
      • Transfer
        • Sample code
      • Submit Order
        • Sample code
      • Cancel Order
        • Sample code
      • Withdraw
        • Sample code
      • Get Transactions
        • Sample code
      • Get Orders
        • Sample code
      • Get Trade History
        • Sample code
  • 🔬Resources
    • Advanced
      • UpdateAccount with custom seed
      • Pay payee updateAccount fee
      • Common error and solutions
      • Submit erc20 order
    • Common Info
      • Get relayer current time
        • Sample code
      • Get exchange info
        • Sample code
      • Get token info
        • Sample code
      • Get markets info
        • Sample code
    • Error codes
    • Fees
      • GET ERC20 Offchain Fee
        • Sample code
      • GET ERC20 Order Fee
        • Sample code
      • GET NFT Offchain Fee
        • Sample code
      • GET NFT Order Fee
        • Sample code
      • SDK Fees
    • Layer 2 block info
      • Get pending transactions
    • Request signing
      • Special API Request Signatures
      • Off-chain Request Signatures
      • Extra ECDSA authentic in header
    • Signature
      • ECDSA signature
        • ECDSA key generation
        • ECDSA sign
        • ECDSA verify signature
      • EdDSA signature
        • EdDSA key generation
        • EdDSA sign
        • EdDSA verify signature
      • SDK Signature
        • Mock Signature
    • Smart Contracts
    • Storage Id
      • Sample code
    • WebSocket
      • Account Notification
      • Order Notification
      • Orderbook Notification
      • Trade Notification
      • Ticker Notification
      • Candlestick Notification
      • AMM Pool Snapshot Notification
      • Block Generation Notification
    • Loopring Smart Wallet
      • Signature and verification
Powered by GitBook
On this page
  • Environment type
  • The following are the provider gateways we inject & test:
  • For signature:
  • Validate signature

Was this helpful?

  1. Resources
  2. Signature

SDK Signature

Loopring SDK supports EOA (EOA hardware wallet) & Loopring Smart Wallet signature

PreviousEdDSA verify signatureNextMock Signature

Last updated 2 years ago

Was this helpful?

Environment type

  • For Browser extension, Dapp, and hardware wallet we only support EOA

  • For Loopring smart wallet (App), the provider gateway is WalletConnect

The following are the provider gateways we inject & test:

  • MetaMask (Ledger, Trezor)

  • WalletConnect (Authereum, Loopring smart wallet )

  • Coinbase

For signature:

Understand what is (eth_sign, personal_sign, v1, v3, v4)

❗ when adding SigSuffix 02|03 (please follow: EIP712 & signTypedData_v4 + 02, personal_sign + 03)

  • for v4 ecdsaSignature, the result signature should + SigSuffix.Suffix02;

  • for personal_sign ecdsaSignature the result signature should + SigSuffix.Suffix03;

EOA:

    • common EOA: we use the v4 signature and web3.eth.personal.ecRecover validate signature

    • when v4 signature fails for any step, we will try personal_sign and web3.eth.personal.ecRecover validate signature

  • For Dapp

    • when loopring DEX is inside Dapp Webview & connect by window.ethereum, we remove the web3.eth.personal.ecRecover validate

Loopring smart wallet:

  • For Loopring smart wallet we send eth_signTypedData by WalletConnect & validate ABI.Contracts.ContractWallet.encodeInputs isValidSignature(bytes32,bytes)

Loopring counterfactual wallet:

  • signature is same as Loopring smart wallet

  • But ecRecover is by walletOwner, const {walletOwner} = await LoopringAPI.exchangeAPI.getCounterFactualInfo({ accountId: LOOPRING_EXPORTED_ACCOUNT.accountIdCF, });

Validate signature

 export async function personalSign(
  web3: any,
  account: string | undefined,
  pwd: string,
  msg: string,
  walletType: ConnectorNames,
  chainId: ChainId,
  accountId?: number,
  counterFactualInfo?: CounterFactualInfo,
  isMobile?: boolean
) {
  if (!account) {
    return { error: "personalSign got no account" };
  }

  return new Promise((resolve) => {
    try {
      web3.eth.personal.sign(
        msg,
        account,
        pwd,
        async function (err: any, result: any) {
          if (!err) {
            // Valid:1. counter Factual signature Valid
            if (counterFactualInfo && accountId) {
              myLog("fcWalletValid counterFactualInfo accountId:");
              const fcValid = await fcWalletValid(
                web3,
                account,
                msg,
                result,
                accountId,
                chainId,
                counterFactualInfo
              );
              if (fcValid.result) {
                resolve({
                  sig: result,
                  counterFactualInfo: fcValid.counterFactualInfo,
                });
                return;
              }
            }

            // Valid: 2. webview directory signature Valid
            if (
              (window?.ethereum?.isImToken || window?.ethereum?.isMetaMask) &&
              isMobile &&
              // Mobile directory connect will sign ConnectorNames as MetaMask only
              walletType === ConnectorNames.MetaMask
            ) {
              const address: string[] = await window.ethereum?.request({
                method: "eth_requestAccounts",
              });
              if (
                address?.find(
                  (item) => item.toLowerCase() === account.toLowerCase()
                )
              ) {
                return resolve({ sig: result });
              }
            }

            // Valid: 3. EOA signature Valid by ecRecover
            const valid: any = await ecRecover(web3, account, msg, result);
            if (valid.result) {
              return resolve({ sig: result });
            }

            // Valid: 4. contractWallet signature Valid `isValidSignature(bytes32,bytes)`
            const walletValid2: any = await contractWalletValidate32(
              web3,
              account,
              msg,
              result
            );

            if (walletValid2.result) {
              return resolve({ sig: result });
            }

            // Valid: 5. counter Factual signature Valid when no counterFactualInfo
            if (accountId) {
              const fcValid = await fcWalletValid(
                web3,
                account,
                msg,
                result,
                accountId,
                chainId
              );
              if (fcValid.result) {
                return resolve({
                  sig: result,
                  counterFactualInfo: fcValid.counterFactualInfo,
                });
              }
            }

            // Valid: 6. myKeyValid Valid again
            const myKeyValid: any = await mykeyWalletValid(
              web3,
              account,
              msg,
              result
            );

            if (myKeyValid.result) {
              return resolve({ sig: result });
            }

            // Valid: Error cannot pass personalSign Valid
            // eslint-disable-next-line no-console
            console.log(
              "web3.eth.personal.sign Valid, valid 5 ways, all failed!"
            );
            return resolve({
              error: "web3.eth.personal.sign Valid, valid 5 ways, all failed!",
            });
          } else {
            return resolve({
              error: "personalSign err before Validate:" + err,
            });
          }
        }
      );
    } catch (reason) {
      resolve({ error: reason });
    }
  });
}

For Browser extension ()

🔬
eth_sign signing types
More information: signing-data
github: src/api/base_api.ts#personalSign