Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 41 additions & 18 deletions src/server/routes/contract/extensions/erc1155/write/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { Type, type Static } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { queueTx } from "../../../../../../db/transactions/queueTx";
import { getContract } from "../../../../../../utils/cache/getContract";
import { getContract } from "thirdweb";
import { safeTransferFrom } from "thirdweb/extensions/erc1155";
import { getChain } from "../../../../../../utils/chain";
import { getChecksumAddress } from "../../../../../../utils/primitiveTypes";
import { thirdwebClient } from "../../../../../../utils/sdk";
import { queueTransaction } from "../../../../../../utils/transaction/queueTransation";
import { AddressSchema } from "../../../../../schemas/address";
import { NumberStringSchema } from "../../../../../schemas/number";
import {
erc1155ContractParamSchema,
requestQuerystringSchema,
Expand All @@ -16,14 +22,17 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
// INPUTS
const requestSchema = erc1155ContractParamSchema;
const requestBodySchema = Type.Object({
to: Type.String({
description: "Address of the wallet to transfer to",
}),
to: {
...AddressSchema,
description: "The recipient address.",
},
tokenId: Type.String({
description: "the tokenId to transfer",
...NumberStringSchema,
description: "The token ID to transfer.",
}),
amount: Type.String({
description: "the amount of tokens to transfer",
...NumberStringSchema,
description: "The amount of tokens to transfer.",
}),
...txOverridesWithValueSchema.properties,
});
Expand Down Expand Up @@ -67,24 +76,38 @@ export async function erc1155transfer(fastify: FastifyInstance) {
"x-backend-wallet-address": walletAddress,
"x-account-address": accountAddress,
"x-idempotency-key": idempotencyKey,
"x-account-factory-address": accountFactoryAddress,
"x-account-salt": accountSalt,
} = request.headers as Static<typeof walletWithAAHeaderSchema>;

const chainId = await getChainIdFromChain(chain);
const contract = await getContract({
chainId,
contractAddress,
walletAddress,
accountAddress,
client: thirdwebClient,
chain: await getChain(chainId),
address: contractAddress,
});
const tx = await contract.erc1155.transfer.prepare(to, tokenId, amount);

const queueId = await queueTx({
tx,
chainId,
simulateTx,
extension: "erc1155",
idempotencyKey,
const transaction = safeTransferFrom({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

safeTransferFrom can fail if the recipient is a contract that does not implement the onReceived hook. This is generally desirable behaviour, but could fail transfers to smart accounts that do not implement this method. Most smart accounts do implement this though, including ours I think, but would be best to confirm once.

contract,
from: getChecksumAddress(walletAddress),
to: getChecksumAddress(to),
tokenId: BigInt(tokenId),
value: BigInt(amount),
data: "0x",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expose data as an optional body param

});

const queueId = await queueTransaction({
transaction,
fromAddress: getChecksumAddress(walletAddress),
toAddress: getChecksumAddress(contractAddress),
Comment on lines +102 to +103
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making sure the from/to here is always backend wallet -> contract (as opposed to above when building the transaction where from/to are the sender/recipient addresses).

accountAddress: getChecksumAddress(accountAddress),
accountFactoryAddress: getChecksumAddress(accountFactoryAddress),
accountSalt,
txOverrides,
idempotencyKey,
shouldSimulate: simulateTx,
functionName: "safeTransferFrom",
extension: "erc1155",
});

reply.status(StatusCodes.OK).send({
Expand Down
79 changes: 49 additions & 30 deletions src/server/routes/contract/extensions/erc1155/write/transferFrom.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { Type, type Static } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { queueTx } from "../../../../../../db/transactions/queueTx";
import { getContract } from "../../../../../../utils/cache/getContract";
import { getContract } from "thirdweb";
import { safeTransferFrom } from "thirdweb/extensions/erc1155";
import { getChain } from "../../../../../../utils/chain";
import { getChecksumAddress } from "../../../../../../utils/primitiveTypes";
import { thirdwebClient } from "../../../../../../utils/sdk";
import { queueTransaction } from "../../../../../../utils/transaction/queueTransation";
import { AddressSchema } from "../../../../../schemas/address";
import { NumberStringSchema } from "../../../../../schemas/number";
import {
erc1155ContractParamSchema,
requestQuerystringSchema,
Expand All @@ -16,18 +22,22 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
// INPUTS
const requestSchema = erc1155ContractParamSchema;
const requestBodySchema = Type.Object({
from: Type.String({
description: "Address of the token owner",
}),
to: Type.String({
description: "Address of the wallet to transferFrom to",
}),
tokenId: Type.String({
description: "the tokenId to transferFrom",
}),
amount: Type.String({
description: "the amount of tokens to transfer",
}),
from: {
...AddressSchema,
description: "The sender address.",
},
to: {
...AddressSchema,
description: "The recipient address.",
},
tokenId: {
...NumberStringSchema,
description: "The token ID to transfer.",
},
amount: {
...NumberStringSchema,
description: "The amount of tokens to transfer.",
},
...txOverridesWithValueSchema.properties,
});

Expand Down Expand Up @@ -74,29 +84,38 @@ export async function erc1155transferFrom(fastify: FastifyInstance) {
"x-backend-wallet-address": walletAddress,
"x-account-address": accountAddress,
"x-idempotency-key": idempotencyKey,
"x-account-factory-address": accountFactoryAddress,
"x-account-salt": accountSalt,
} = request.headers as Static<typeof walletWithAAHeaderSchema>;

const chainId = await getChainIdFromChain(chain);
const contract = await getContract({
chainId,
contractAddress,
walletAddress,
accountAddress,
client: thirdwebClient,
chain: await getChain(chainId),
address: contractAddress,
});
const tx = await contract.erc1155.transferFrom.prepare(
from,
to,
tokenId,
amount,
);

const queueId = await queueTx({
tx,
chainId,
simulateTx,
extension: "erc1155",
idempotencyKey,
const transaction = safeTransferFrom({
contract,
from: getChecksumAddress(from),
to: getChecksumAddress(to),
tokenId: BigInt(tokenId),
value: BigInt(amount),
data: "0x",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

expose data here too, and all the other routes

});

const queueId = await queueTransaction({
transaction,
fromAddress: getChecksumAddress(walletAddress),
toAddress: getChecksumAddress(contractAddress),
accountAddress: getChecksumAddress(accountAddress),
accountFactoryAddress: getChecksumAddress(accountFactoryAddress),
accountSalt,
txOverrides,
idempotencyKey,
shouldSimulate: simulateTx,
functionName: "safeTransferFrom",
extension: "erc1155",
});

reply.status(StatusCodes.OK).send({
Expand Down
51 changes: 34 additions & 17 deletions src/server/routes/contract/extensions/erc20/write/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { Type, type Static } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { queueTx } from "../../../../../../db/transactions/queueTx";
import { getContract } from "../../../../../../utils/cache/getContract";
import { getContract } from "thirdweb";
import { transfer } from "thirdweb/extensions/erc20";
import { getChain } from "../../../../../../utils/chain";
import { getChecksumAddress } from "../../../../../../utils/primitiveTypes";
import { thirdwebClient } from "../../../../../../utils/sdk";
import { queueTransaction } from "../../../../../../utils/transaction/queueTransation";
import { AddressSchema } from "../../../../../schemas/address";
import { TokenAmountStringSchema } from "../../../../../schemas/number";
import {
erc20ContractParamSchema,
requestQuerystringSchema,
Expand All @@ -14,15 +19,15 @@ import { txOverridesWithValueSchema } from "../../../../../schemas/txOverrides";
import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet";
import { getChainIdFromChain } from "../../../../../utils/chain";

// INPUTS
const requestSchema = erc20ContractParamSchema;
const requestBodySchema = Type.Object({
toAddress: {
...AddressSchema,
description: "Address of the wallet you want to send the tokens to",
description: "The recipient address.",
},
amount: Type.String({
description: "The amount of tokens you want to send",
...TokenAmountStringSchema,
description: "The amount of tokens to transfer.",
}),
...txOverridesWithValueSchema.properties,
});
Expand All @@ -49,7 +54,7 @@ export async function erc20Transfer(fastify: FastifyInstance) {
description:
"Transfer ERC-20 tokens from the caller wallet to a specific wallet.",
tags: ["ERC20"],
operationId: "erc20-erc20-transfer",
operationId: "erc20-transfer",
body: requestBodySchema,
params: requestSchema,
headers: walletWithAAHeaderSchema,
Expand All @@ -67,23 +72,35 @@ export async function erc20Transfer(fastify: FastifyInstance) {
"x-backend-wallet-address": walletAddress,
"x-account-address": accountAddress,
"x-idempotency-key": idempotencyKey,
"x-account-factory-address": accountFactoryAddress,
"x-account-salt": accountSalt,
} = request.headers as Static<typeof walletWithAAHeaderSchema>;

const chainId = await getChainIdFromChain(chain);
const contract = await getContract({
chainId,
contractAddress,
walletAddress,
accountAddress,
client: thirdwebClient,
chain: await getChain(chainId),
address: contractAddress,
});
const tx = await contract.erc20.transfer.prepare(toAddress, amount);
const queueId = await queueTx({
tx,
chainId,
simulateTx,
extension: "erc20",
idempotencyKey,

const transaction = transfer({
contract,
to: getChecksumAddress(toAddress),
amount,
});

const queueId = await queueTransaction({
transaction,
fromAddress: getChecksumAddress(walletAddress),
toAddress: getChecksumAddress(contractAddress),
accountAddress: getChecksumAddress(accountAddress),
accountFactoryAddress: getChecksumAddress(accountFactoryAddress),
accountSalt,
txOverrides,
idempotencyKey,
shouldSimulate: simulateTx,
functionName: "transfer",
extension: "erc20",
});

reply.status(StatusCodes.OK).send({
Expand Down
57 changes: 35 additions & 22 deletions src/server/routes/contract/extensions/erc20/write/transferFrom.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { Type, type Static } from "@sinclair/typebox";
import type { FastifyInstance } from "fastify";
import { StatusCodes } from "http-status-codes";
import { queueTx } from "../../../../../../db/transactions/queueTx";
import { getContract } from "../../../../../../utils/cache/getContract";
import { getContract } from "thirdweb";
import { transferFrom } from "thirdweb/extensions/erc20";
import { getChain } from "../../../../../../utils/chain";
import { getChecksumAddress } from "../../../../../../utils/primitiveTypes";
import { thirdwebClient } from "../../../../../../utils/sdk";
import { queueTransaction } from "../../../../../../utils/transaction/queueTransation";
import { AddressSchema } from "../../../../../schemas/address";
import { TokenAmountStringSchema } from "../../../../../schemas/number";
import {
erc20ContractParamSchema,
requestQuerystringSchema,
Expand All @@ -14,20 +19,20 @@ import { txOverridesWithValueSchema } from "../../../../../schemas/txOverrides";
import { walletWithAAHeaderSchema } from "../../../../../schemas/wallet";
import { getChainIdFromChain } from "../../../../../utils/chain";

// INPUTS
const requestSchema = erc20ContractParamSchema;
const requestBodySchema = Type.Object({
fromAddress: {
...AddressSchema,
description: "Address of the wallet sending the tokens",
description: "The sender address.",
},
toAddress: {
...AddressSchema,
description: "Address of the wallet you want to send the tokens to",
description: "The recipient address.",
},
amount: {
...TokenAmountStringSchema,
description: "The amount of tokens to transfer.",
},
amount: Type.String({
description: "The amount of tokens you want to send",
}),
...txOverridesWithValueSchema.properties,
});

Expand Down Expand Up @@ -74,28 +79,36 @@ export async function erc20TransferFrom(fastify: FastifyInstance) {
"x-backend-wallet-address": walletAddress,
"x-account-address": accountAddress,
"x-idempotency-key": idempotencyKey,
"x-account-factory-address": accountFactoryAddress,
"x-account-salt": accountSalt,
} = request.headers as Static<typeof walletWithAAHeaderSchema>;

const chainId = await getChainIdFromChain(chain);
const contract = await getContract({
chainId,
contractAddress,
walletAddress,
accountAddress,
client: thirdwebClient,
chain: await getChain(chainId),
address: contractAddress,
});
const tx = await contract.erc20.transferFrom.prepare(
fromAddress,
toAddress,

const transaction = transferFrom({
contract,
from: getChecksumAddress(fromAddress),
to: getChecksumAddress(toAddress),
amount,
);
});

const queueId = await queueTx({
tx,
chainId,
simulateTx,
extension: "erc20",
idempotencyKey,
const queueId = await queueTransaction({
transaction,
fromAddress: getChecksumAddress(walletAddress),
toAddress: getChecksumAddress(contractAddress),
accountAddress: getChecksumAddress(accountAddress),
accountFactoryAddress: getChecksumAddress(accountFactoryAddress),
accountSalt,
txOverrides,
idempotencyKey,
shouldSimulate: simulateTx,
functionName: "transferFrom",
extension: "erc20",
});

reply.status(StatusCodes.OK).send({
Expand Down
Loading
Loading