Private NFT Transfers
Private Transfers require you to "Generate Proof" and, optionally, make use of "Broadcasters": See UX for Private Transactions
RAILGUN users may transfer multiple ERC-721 tokens to other RAILGUN users in a single transaction, in a fully encrypted and privacy-preserving way.
ERC-1155 token transfers are not yet supported.
Imports
import {
calculateGasPrice,
TXIDVersion,
type NetworkName,
type RailgunERC20AmountRecipient,
type RailgunNFTAmountRecipient,
type RailgunWalletInfo,
type TransactionGasDetails,
} from "@railgun-community/shared-models";
import {
getGasDetailsForTransaction,
getOriginalGasDetailsForTransaction,
serializeERC721Transfer,
} from "../util";
import {
gasEstimateForUnprovenTransfer,
generateTransferProof,
populateProvedTransfer,
} from "@railgun-community/wallet";
import {
TEST_NETWORK,
TEST_NFT_ADDRESS,
TEST_NFT_SUBID,
} from "../../utils/constants";
import { getProviderWallet } from "../../utils/provider";
Gas Estimate
export const erc721PrivateTransferGasEstimate = async (
encryptionKey: string,
network: NetworkName,
railgunWalletID: string,
erc721AmountRecipients: RailgunNFTAmountRecipient[],
sendWithPublicWallet: boolean = true,
feeTokenDetails: RailgunERC20AmountRecipient | undefined = undefined,
memoText: string | undefined = undefined
) => {
const originalGasDetails = await getOriginalGasDetailsForTransaction(
network,
sendWithPublicWallet
);
console.log("originalGasDetails: ", originalGasDetails);
const { gasEstimate } = await gasEstimateForUnprovenTransfer(
TXIDVersion.V2_PoseidonMerkle,
network,
railgunWalletID,
encryptionKey,
memoText,
[],
erc721AmountRecipients,
originalGasDetails,
feeTokenDetails,
sendWithPublicWallet
);
return gasEstimate;
};
Generate Proof
export const erc721PrivateTransferGenerateProof = async (
encryptionKey: string,
network: NetworkName,
railgunWalletID: string,
erc721AmountRecipients: RailgunNFTAmountRecipient[],
overallBatchMinGasPrice: bigint,
showSenderAddressToRecipient: boolean = true,
sendWithPublicWallet: boolean = true,
broadcasterFeeERC20AmountRecipient:
| RailgunERC20AmountRecipient
| undefined = undefined,
memoText: string | undefined = undefined
) => {
const progressCallback = (progress: number) => {
// Handle proof progress (show in UI).
// Proofs can take 20-30 seconds on slower devices.
console.log("Private ERC721 Transfer Proof progress: ", progress);
};
await generateTransferProof(
TXIDVersion.V2_PoseidonMerkle,
network,
railgunWalletID,
encryptionKey,
showSenderAddressToRecipient,
memoText,
[],
erc721AmountRecipients,
broadcasterFeeERC20AmountRecipient,
sendWithPublicWallet,
overallBatchMinGasPrice,
progressCallback
);
};
Populate Transaction
export const erc721PrivateTransferPopulateTransaction = async (
network: NetworkName,
railgunWalletID: string,
erc721AmountRecipients: RailgunNFTAmountRecipient[],
overallBatchMinGasPrice: bigint,
transactionGasDetails: TransactionGasDetails,
sendWithPublicWallet: boolean = true,
broadcasterFeeERC20AmountRecipient:
| RailgunERC20AmountRecipient
| undefined = undefined,
showSenderAddressToRecipient: boolean = true,
memoText: string | undefined = undefined
) => {
const populateResponse = await populateProvedTransfer(
TXIDVersion.V2_PoseidonMerkle,
network,
railgunWalletID,
showSenderAddressToRecipient,
memoText,
[], // erc20AmountRecipients
erc721AmountRecipients,
broadcasterFeeERC20AmountRecipient,
sendWithPublicWallet,
overallBatchMinGasPrice,
transactionGasDetails
);
return populateResponse;
};
Example Usage
export const TEST_ERC721PrivateTransfer = async (
encryptionKey: string,
railgunWalletInfo: RailgunWalletInfo
) => {
const { wallet } = getProviderWallet();
const nftAddress = TEST_NFT_ADDRESS;
const tokenSubID = TEST_NFT_SUBID;
const erc721AmountRecipients = [
serializeERC721Transfer(
nftAddress,
tokenSubID,
railgunWalletInfo.railgunAddress
),
];
const gasEstimate = await erc721PrivateTransferGasEstimate(
encryptionKey,
TEST_NETWORK,
railgunWalletInfo.id,
erc721AmountRecipients
);
console.log("Private ERC721 TX gasEstimate: ", gasEstimate);
await erc721PrivateTransferGenerateProof(
encryptionKey,
TEST_NETWORK,
railgunWalletInfo.id,
erc721AmountRecipients,
1n
);
const transactionGasDetails = await getGasDetailsForTransaction(
TEST_NETWORK,
gasEstimate,
true,
wallet
);
const overallBatchMinGasPrice = calculateGasPrice(transactionGasDetails);
const transaction = await erc721PrivateTransferPopulateTransaction(
TEST_NETWORK,
railgunWalletInfo.id,
erc721AmountRecipients,
overallBatchMinGasPrice,
transactionGasDetails
);
console.log("ERC721 transaction: ", transaction);
// send private ERC721 tx via self-signed tx or broadcaster.
};
Last updated