Paymaster API

const baseUrl = "https://paymaster.kanalabs.io"
const projectKey = process.env.PROJECT_KEY
const network = Network.MAINNET // mainnet
const chain = chainName.Aptos // aptos 
const headers = {
      'Content-Type': 'application/json',
      'api-key': projectKey,
       network: network ?? Network.MAINNET,
       chain: chain ?? chainName.Aptos,
    }

To initialize Aptos account

Note: The address needs to be whitelisted before initializing it

  async initAccount() {
    const url = `${baseUrl}/initAccount`
    const params = { address: "0x0b4b8ef78fb296f89006f1936f01427a3a7e0eadd11dd4998c6bf438a0c8ce6b" }
    try {
      const response = await axios.get(url, { params, headers })
      return response.data
    } catch (error: any) {
      throw error?.data || error
    }
  }

To whitelist an address

  async addToWhitelist() {
    const url = `${baseUrl}/addToWhitelist`
    const params = { user_address: "0x0b4b8ef78fb296f89006f1936f01427a3a7e0eadd11dd4998c6bf438a0c8ce6b" }
    try {
      const response = await axios.get(url, { params, headers })
      return response.data
    } catch (error: any) {
      throw error?.data || error
    }
  }

To disable user

Note: To stop/pause users from using sponsored txns

  async disableUser() {
    const url = `${baseUrl}/modifyUserState`
    const params = { user_address: "0x0b4b8ef78fb296f89006f1936f01427a3a7e0eadd11dd4998c6bf438a0c8ce6b", status: false }
    try {
      const response = await axios.get(url, { params, headers })
      return response.data
    } catch (error: any) {
      throw error?.data || error
    }
  }

To enable user

Note: To resume sponsored txns for a user

 async enableUser() {
    const url = `${baseUrl}/modifyUserState`
    const params = { user_address: "0x0b4b8ef78fb296f89006f1936f01427a3a7e0eadd11dd4998c6bf438a0c8ce6b", status: true } 
    try {
      const response = await axios.get(url, { params, headers })
      return response.data
    } catch (error: any) {
      throw error?.data || error
    }
  }

Is whitelisted

Note: To check whether an address is already whitelisted or not

  async isWhitelisted() {
    const url = `${baseUrl}/isWhitelisted`
    const params = { user_address: "0x0b4b8ef78fb296f89006f1936f01427a3a7e0eadd11dd4998c6bf438a0c8ce6b"}
    try {
      const response = await axios.get(url, { params, headers })
      return response.data
    } catch (error: any) {
      throw error?.data || error
    }
  }

Build txn with feepayer : true and send it to /sponsorGas endpoint with api-key it will return { feePayerAddress, feePayerAuth }

async sponsoredTxn(args: {
    data: TransactionPayload | SupraPayload
    senderAddress?: string
    senderAuth?: TxnBuilderTypes.AccountAuthenticatorEd25519
    transaction?: TxnBuilderTypes.RawTransaction
    options?: TransactionOptions
  }): Promise<PendingTransactionResponse | PendingTransactionResponseForSupra> {
    try {
      if (this.wallet === undefined) {
        throw new Error('No wallet')
      }
      let rawTransactionBytes: Uint8Array
      let committedTxn: TransactionResponse | PendingTransactionResponse
      let senderAuth: AccountAuthenticator | TxnBuilderTypes.AccountAuthenticatorEd25519
      let transaction: SimpleTransaction

      if (this.chain === chainName.Supra) {
        rawTransactionBytes = BCS.bcsToBytes(args.transaction)
      } else {
        transaction = await this.aptosClient.transaction.build.simple({
          sender: this.wallet.accountAddress.toString(),
          data: args.data as TransactionPayload,
          options: args.options,
          withFeePayer: true,
        })

        senderAuth = this.aptosClient.transaction.sign({
          signer: this.wallet,
          transaction,
        })

        rawTransactionBytes = transaction.rawTransaction.bcsToBytes()
      }

      const url = `${this.baseUrl}/sponsorGas`
      const headers = this.getCommonHeaders()
      const response = await fetch(url, {
        method: 'POST',
        headers: headers,
        body: JSON.stringify({ data: rawTransactionBytes }),
      })
      if (response.status >= 400) {
        await response.json().then((data) => {
          throw new Error(data?.error || data?.message || 'Error in sponsoring transaction.')
        })
      }
      const responseData = await response.json()
      const feePayerAddress = responseData.feePayerAddress
      const feepayerSignature = new Uint8Array(Object.values(responseData.feePayerAuth))

      if (this.chain === chainName.Supra) {
        const deserializerFeePayer = new BCS.Deserializer(feepayerSignature)
        const feepayerAuth = TxnBuilderTypes.AccountAuthenticatorEd25519.deserialize(
          deserializerFeePayer,
        ) as TxnBuilderTypes.AccountAuthenticatorEd25519
        committedTxn = await this.SupraClient.sendSponsorTransaction(
          args.senderAddress,
          feePayerAddress,
          [],
          args.transaction,
          args.senderAuth,
          feepayerAuth,
          [],
          {
            enableWaitForTransaction: true,
            enableTransactionSimulation: true,
          },
        )
      } else {
        const deserializerFeePayer: any = new Deserializer(feepayerSignature)
        const feepayerAuth = AccountAuthenticator.deserialize(deserializerFeePayer)
        committedTxn = await this.aptosClient.transaction.submit.simple({
          transaction: {
            rawTransaction: transaction.rawTransaction as any,
            feePayerAddress: AccountAddress.fromString(feePayerAddress),
          } as AnyRawTransaction,
          senderAuthenticator: senderAuth as AccountAuthenticator,
          feePayerAuthenticator: feepayerAuth as AccountAuthenticator,
        })
      }
      return committedTxn
    } catch (error: any) {
      throw error?.response?.data || error
    }
  }

Last updated