@myria/airdrop-js
Version:
Airdrop in L1 with claim based approach
104 lines • 9.81 kB
JavaScript
;
/**
* Collection of wrapper functions which include single functions in core to simplify consumers's integration like plug (config in) and play
* @module Transaction/Wrapper
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.approveWhitelistAndAllowance = exports.saveMerkleTreeByOwner = void 0;
const ErrorCodeType_1 = require("../type/ErrorCodeType");
const core_1 = require("./core");
const internalUse_1 = require("./internalUse");
const validation_1 = require("./validation");
/**
* Wrapper function: Airdrop's owner approve whitelist to save on-chain include both setMerkleRoot and saveSnapshot
*
* @param {Account} account - The Account represent as sender @see {@link https://ethereum.org/en/glossary/#account|Account's Ethereum}.
* @param {string} merkleRoot - The generated merkleRoot from whitelist @see {@link generateMerkleTreeInfoERC20ForWhitelist|Generate merkleRoot}
* @param {string} snapshotUri - The generated snapshotUri from whitelist @see {@link generateMerkleTreeInfoERC20ForWhitelist|Generate snapshotUri}
* @param {ThirdwebContract} airdropContract - The airdrop Thirdweb contract.
* @param {Address} tokenAddress - The token address to claim.
* @param {RetryOptions} retryOptions - The configuration on retry
* @param {ExtraGasOptions} extraGasOptions - The extra gas options bidding for your transaction to be included in the next block.
* @returns {Promise<SaveMerkleTreeResult>} A promise that resolves to the confirmed transaction hashes accordingly.
*/
async function saveMerkleTreeByOwner(account, merkleRoot, snapshotUri, airdropContract, tokenAddress, retryOptions = {}, extraGasOptions = {}) {
const startTime = (0, internalUse_1.logFunctionTrackStartTime)(saveMerkleTreeByOwner.name);
// Check to skip approve allowance to reduce our cost
const shouldSkipSubmitting = await (0, validation_1.isAlreadySubmittedOnchain)(airdropContract, tokenAddress, merkleRoot);
if (shouldSkipSubmitting) {
(0, internalUse_1.logFunctionDuration)(saveMerkleTreeByOwner.name, startTime);
return {
snapshotResult: ErrorCodeType_1.ALREADY_SUBMITTED_SKIP_TRANSACTION,
merkleRootResult: ErrorCodeType_1.ALREADY_SUBMITTED_SKIP_TRANSACTION,
};
}
// Save snapshot
const { transactionHash: snapshotTransactionHash } = await (0, core_1.saveSnapshotByOwner)(account, airdropContract, merkleRoot, snapshotUri, retryOptions, extraGasOptions);
const snapshotResult = { transactionHash: snapshotTransactionHash };
// Set MerkleRoot
const { transactionHash: merkleRootTransactionHash } = await (0, core_1.saveMerkleRootByOwner)(account, airdropContract, tokenAddress, merkleRoot, retryOptions, extraGasOptions);
const merkleRootResult = { transactionHash: merkleRootTransactionHash };
(0, internalUse_1.logFunctionDuration)(saveMerkleTreeByOwner.name, startTime);
// In case of resubmit with the same data. The transaction hash will be empty
return {
snapshotResult,
merkleRootResult,
};
}
exports.saveMerkleTreeByOwner = saveMerkleTreeByOwner;
/**
* Wrapper function: Owner approve the whitelist on behalf of Airdrop's contract owner and approve allowance on behalf of Token's contract owner.
*
* @param {Account} account - The Account represent as sender @see {@link https://ethereum.org/en/glossary/#account|Account's Ethereum}.
* @param {string} merkleRoot - The generated merkleRoot from whitelist @see {@link generateMerkleTreeInfoERC20ForWhitelist|Generate merkleRoot}
* @param {string} snapshotUri - The generated snapshotUri from whitelist @see {@link generateMerkleTreeInfoERC20ForWhitelist|Generate snapshotUri}
* @param {ThirdwebContract} airdropContract - The airdrop Thirdweb contract.
* @param {ThirdwebContract} tokenContract - The token Thirdweb contract to airdrop
* @param {number} totalAmount - The total airdrop amount in ether format.
* @param {RetryOptions} retryOptions - The configuration on retry
* @param {ExtraGasOptions} extraGasOptions - The extra gas options bidding for your transaction to be included in the next block.
* @returns {Promise<ApproveWhitelistAndAllowanceResult>} A promise that resolves to the confirmed transaction hashes accordingly.
* @throws An error if the totalAmount <= 0.
*/
async function approveWhitelistAndAllowance(account, merkleRoot, snapshotUri, airdropContract, tokenContract, totalAmount, retryOptions = {}, extraGasOptions = {}) {
if (totalAmount <= 0) {
throw Error('totalAmount must be greater than 0');
}
const ownerAddress = await (0, core_1.getOwnerOfContract)(airdropContract);
if (account.address.toLowerCase() !== ownerAddress.toLowerCase()) {
throw Error('account must belong to airdropContract owner');
}
const startTime = (0, internalUse_1.logFunctionTrackStartTime)(approveWhitelistAndAllowance.name);
// Save MerkleTree on-chain
const saveMerkleTreeResult = await saveMerkleTreeByOwner(account, merkleRoot, snapshotUri, airdropContract, tokenContract.address, retryOptions, extraGasOptions);
// Approve Allowance
// Check to skip approve allowance to reduce our cost
const shouldSkipApproveSpender = await (0, validation_1.isAlreadyApprovedAllowanceOnchain)(account.address, airdropContract.address, tokenContract, totalAmount);
if (shouldSkipApproveSpender) {
(0, internalUse_1.logFunctionDuration)(approveWhitelistAndAllowance.name, startTime);
return {
...saveMerkleTreeResult,
approveAllowanceResult: ErrorCodeType_1.ALREADY_SUBMITTED_SKIP_TRANSACTION,
};
}
let approveAllowanceResult;
try {
const { transactionHash } = await (0, core_1.approveAirdropAsSpender)(airdropContract.address, totalAmount, account, tokenContract);
approveAllowanceResult = {
transactionHash,
};
}
catch (error) {
approveAllowanceResult = {
...ErrorCodeType_1.GENERIC_ERROR,
errorMessage: error.message,
};
}
(0, internalUse_1.logFunctionDuration)(approveWhitelistAndAllowance.name, startTime);
return {
...saveMerkleTreeResult,
approveAllowanceResult: approveAllowanceResult,
};
}
exports.approveWhitelistAndAllowance = approveWhitelistAndAllowance;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3JhcHBlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90cmFuc2FjdGlvbi93cmFwcGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7OztBQVdILHlEQUcrQjtBQUMvQixpQ0FPZ0I7QUFDaEIsK0NBQStFO0FBQy9FLDZDQUdzQjtBQUV0Qjs7Ozs7Ozs7Ozs7R0FXRztBQUNJLEtBQUssVUFBVSxxQkFBcUIsQ0FDdkMsT0FBZ0IsRUFDaEIsVUFBa0IsRUFDbEIsV0FBbUIsRUFDbkIsZUFBaUMsRUFDakMsWUFBb0IsRUFDcEIsZUFBNkIsRUFBRSxFQUMvQixrQkFBbUMsRUFBRTtJQUVyQyxNQUFNLFNBQVMsR0FBRyxJQUFBLHVDQUF5QixFQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hFLHFEQUFxRDtJQUNyRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sSUFBQSxzQ0FBeUIsRUFDeEQsZUFBZSxFQUNmLFlBQVksRUFDWixVQUFVLENBQ2IsQ0FBQztJQUNGLElBQUksb0JBQW9CLEVBQUUsQ0FBQztRQUN2QixJQUFBLGlDQUFtQixFQUFDLHFCQUFxQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztRQUMzRCxPQUFPO1lBQ0gsY0FBYyxFQUFFLGtEQUFrQztZQUNsRCxnQkFBZ0IsRUFBRSxrREFBa0M7U0FDdkQsQ0FBQztJQUNOLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsTUFBTSxFQUFFLGVBQWUsRUFBRSx1QkFBdUIsRUFBRSxHQUM5QyxNQUFNLElBQUEsMEJBQW1CLEVBQ3JCLE9BQU8sRUFDUCxlQUFlLEVBQ2YsVUFBVSxFQUNWLFdBQVcsRUFDWCxZQUFZLEVBQ1osZUFBZSxDQUNsQixDQUFDO0lBQ04sTUFBTSxjQUFjLEdBQUcsRUFBRSxlQUFlLEVBQUUsdUJBQXVCLEVBQUUsQ0FBQztJQUVwRSxpQkFBaUI7SUFDakIsTUFBTSxFQUFFLGVBQWUsRUFBRSx5QkFBeUIsRUFBRSxHQUNo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