@mysten/suins
Version:
460 lines (459 loc) • 17.9 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var suins_transaction_exports = {};
__export(suins_transaction_exports, {
SuinsTransaction: () => SuinsTransaction
});
module.exports = __toCommonJS(suins_transaction_exports);
var import_bcs = require("@mysten/sui/bcs");
var import_utils = require("@mysten/sui/utils");
var import_constants = require("./constants.js");
var import_helpers = require("./helpers.js");
class SuinsTransaction {
constructor(client, transaction) {
this.suinsClient = client;
this.transaction = transaction;
}
/**
* Registers a domain for a number of years.
*/
register(params) {
if (params.couponCode && params.discountInfo) {
throw new Error("Cannot apply both coupon and discount NFT");
}
const paymentIntent = this.initRegistration(params.domain);
if (params.couponCode) {
this.applyCoupon(paymentIntent, params.couponCode);
}
if (params.discountInfo) {
this.applyDiscount(paymentIntent, params.discountInfo);
}
const priceAfterDiscount = this.calculatePriceAfterDiscount(
paymentIntent,
params.coinConfig.type
);
const receipt = this.generateReceipt({
paymentIntent,
priceAfterDiscount,
coinConfig: params.coinConfig,
coin: params.coin,
maxAmount: params.maxAmount,
priceInfoObjectId: params.priceInfoObjectId
});
const nft = this.finalizeRegister(receipt);
if (params.years > 1) {
this.renew({
nft,
years: params.years - 1,
coinConfig: params.coinConfig,
coin: params.coin,
couponCode: params.couponCode,
discountInfo: params.discountInfo,
maxAmount: params.maxAmount,
priceInfoObjectId: params.priceInfoObjectId
});
}
return nft;
}
/**
* Renews an NFT for a number of years.
*/
renew(params) {
if (params.couponCode && params.discountInfo) {
throw new Error("Cannot apply both coupon and discount NFT");
}
const paymentIntent = this.initRenewal(params.nft, params.years);
if (params.couponCode) {
this.applyCoupon(paymentIntent, params.couponCode);
}
if (params.discountInfo) {
this.applyDiscount(paymentIntent, params.discountInfo);
}
const priceAfterDiscount = this.calculatePriceAfterDiscount(
paymentIntent,
params.coinConfig.type
);
const receipt = this.generateReceipt({
paymentIntent,
priceAfterDiscount,
coinConfig: params.coinConfig,
coin: params.coin,
maxAmount: params.maxAmount,
priceInfoObjectId: params.priceInfoObjectId
});
this.finalizeRenew(receipt, params.nft);
}
initRegistration(domain) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.packageId}::payment::init_registration`,
arguments: [this.transaction.object(config.suins), this.transaction.pure.string(domain)]
});
}
initRenewal(nft, years) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.packageId}::payment::init_renewal`,
arguments: [
this.transaction.object(config.suins),
this.transaction.object(nft),
this.transaction.pure.u8(years)
]
});
}
calculatePrice(baseAmount, paymentType, priceInfoObjectId) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.payments.packageId}::payments::calculate_price`,
arguments: [
this.transaction.object(config.suins),
baseAmount,
this.transaction.object.clock(),
this.transaction.object(priceInfoObjectId)
],
typeArguments: [paymentType]
});
}
handleBasePayment(paymentIntent, payment, paymentType) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.payments.packageId}::payments::handle_base_payment`,
arguments: [this.transaction.object(config.suins), paymentIntent, payment],
typeArguments: [paymentType]
});
}
handlePayment(paymentIntent, payment, paymentType, priceInfoObjectId, maxAmount = import_constants.MAX_U64) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.payments.packageId}::payments::handle_payment`,
arguments: [
this.transaction.object(config.suins),
paymentIntent,
payment,
this.transaction.object.clock(),
this.transaction.object(priceInfoObjectId),
this.transaction.pure.u64(maxAmount)
],
typeArguments: [paymentType]
});
}
finalizeRegister(receipt) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.packageId}::payment::register`,
arguments: [receipt, this.transaction.object(config.suins), this.transaction.object.clock()]
});
}
finalizeRenew(receipt, nft) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.packageId}::payment::renew`,
arguments: [
receipt,
this.transaction.object(config.suins),
this.transaction.object(nft),
this.transaction.object.clock()
]
});
}
calculatePriceAfterDiscount(paymentIntent, paymentType) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.payments.packageId}::payments::calculate_price_after_discount`,
arguments: [this.transaction.object(config.suins), paymentIntent],
typeArguments: [paymentType]
});
}
generateReceipt(params) {
const baseAssetPurchase = params.coinConfig.feed === "";
if (baseAssetPurchase) {
const payment = params.coin ? this.transaction.splitCoins(this.transaction.object(params.coin), [
params.priceAfterDiscount
]) : (0, import_helpers.zeroCoin)(this.transaction, params.coinConfig.type);
const receipt = this.handleBasePayment(params.paymentIntent, payment, params.coinConfig.type);
return receipt;
} else {
const priceInfoObjectId = params.priceInfoObjectId;
if (!priceInfoObjectId)
throw new Error("Price info object ID is required for non-base asset purchases");
const price = this.calculatePrice(
params.priceAfterDiscount,
params.coinConfig.type,
priceInfoObjectId
);
if (!params.coin) throw new Error("coin input is required");
const payment = this.transaction.splitCoins(this.transaction.object(params.coin), [price]);
const receipt = this.handlePayment(
params.paymentIntent,
payment,
params.coinConfig.type,
priceInfoObjectId,
params.maxAmount
);
return receipt;
}
}
/**
* Applies a coupon to the payment intent.
*/
applyCoupon(intent, couponCode) {
const config = this.suinsClient.config;
return this.transaction.moveCall({
target: `${config.coupons.packageId}::coupon_house::apply_coupon`,
arguments: [
this.transaction.object(config.suins),
intent,
this.transaction.pure.string(couponCode),
this.transaction.object.clock()
]
});
}
/**
* Applies a discount to the payment intent.
*/
applyDiscount(intent, discountInfo) {
const config = this.suinsClient.config;
if (discountInfo.isFreeClaim) {
this.transaction.moveCall({
target: `${config.discountsPackage.packageId}::free_claims::free_claim`,
arguments: [
this.transaction.object(config.discountsPackage.discountHouseId),
this.transaction.object(config.suins),
intent,
this.transaction.object(discountInfo.discountNft)
],
typeArguments: [discountInfo.type]
});
} else {
this.transaction.moveCall({
target: `${config.discountsPackage.packageId}::discounts::apply_percentage_discount`,
arguments: [
this.transaction.object(config.discountsPackage.discountHouseId),
intent,
this.transaction.object(config.suins),
this.transaction.object(discountInfo.discountNft)
],
typeArguments: [discountInfo.type]
});
}
}
/**
* Creates a subdomain.
*/
createSubName({
parentNft,
name,
expirationTimestampMs,
allowChildCreation,
allowTimeExtension
}) {
if (!(0, import_utils.isValidSuiNSName)(name)) throw new Error("Invalid SuiNS name");
const isParentSubdomain = (0, import_helpers.isNestedSubName)(name);
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (!this.suinsClient.config.subNamesPackageId)
throw new Error("Subnames package ID not found");
if (isParentSubdomain && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
const subNft = this.transaction.moveCall({
target: isParentSubdomain ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::new` : `${this.suinsClient.config.subNamesPackageId}::subdomains::new`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(parentNft),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID),
this.transaction.pure.string((0, import_utils.normalizeSuiNSName)(name, "dot")),
this.transaction.pure.u64(expirationTimestampMs),
this.transaction.pure.bool(!!allowChildCreation),
this.transaction.pure.bool(!!allowTimeExtension)
]
});
return subNft;
}
/**
* Builds the PTB to create a leaf subdomain.
* Parent can be a `SuinsRegistration` or a `SubDomainRegistration` object.
* Can be passed in as an ID or a TransactionArgument.
*/
createLeafSubName({
parentNft,
name,
targetAddress
}) {
if (!(0, import_utils.isValidSuiNSName)(name)) throw new Error("Invalid SuiNS name");
const isParentSubdomain = (0, import_helpers.isNestedSubName)(name);
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (!this.suinsClient.config.subNamesPackageId)
throw new Error("Subnames package ID not found");
if (isParentSubdomain && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
this.transaction.moveCall({
target: isParentSubdomain ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::new_leaf` : `${this.suinsClient.config.subNamesPackageId}::subdomains::new_leaf`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(parentNft),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID),
this.transaction.pure.string((0, import_utils.normalizeSuiNSName)(name, "dot")),
this.transaction.pure.address(targetAddress)
]
});
}
/**
* Removes a leaf subname.
*/
removeLeafSubName({ parentNft, name }) {
if (!(0, import_utils.isValidSuiNSName)(name)) throw new Error("Invalid SuiNS name");
const isParentSubdomain = (0, import_helpers.isNestedSubName)(name);
if (!(0, import_helpers.isSubName)(name)) throw new Error("This can only be invoked for subnames");
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (!this.suinsClient.config.subNamesPackageId)
throw new Error("Subnames package ID not found");
if (isParentSubdomain && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
this.transaction.moveCall({
target: isParentSubdomain ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::remove_leaf` : `${this.suinsClient.config.subNamesPackageId}::subdomains::remove_leaf`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(parentNft),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID),
this.transaction.pure.string((0, import_utils.normalizeSuiNSName)(name, "dot"))
]
});
}
/**
* Sets the target address of an NFT.
*/
setTargetAddress({
nft,
// Can be string or argument
address,
isSubname
}) {
if (isSubname && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
this.transaction.moveCall({
target: isSubname ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::set_target_address` : `${this.suinsClient.config.packageId}::controller::set_target_address`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(nft),
this.transaction.pure(import_bcs.bcs.option(import_bcs.bcs.Address).serialize(address).toBytes()),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID)
]
});
}
/**
* Sets a default name for the user.
*/
setDefault(name) {
if (!(0, import_utils.isValidSuiNSName)(name)) throw new Error("Invalid SuiNS name");
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
this.transaction.moveCall({
target: `${this.suinsClient.config.packageId}::controller::set_reverse_lookup`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.pure.string((0, import_utils.normalizeSuiNSName)(name, "dot"))
]
});
}
/**
* Edits the setup of a subname.
*/
editSetup({
parentNft,
name,
allowChildCreation,
allowTimeExtension
}) {
if (!(0, import_utils.isValidSuiNSName)(name)) throw new Error("Invalid SuiNS name");
const isParentSubdomain = (0, import_helpers.isNestedSubName)(name);
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (!isParentSubdomain && !this.suinsClient.config.subNamesPackageId)
throw new Error("Subnames package ID not found");
if (isParentSubdomain && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
this.transaction.moveCall({
target: isParentSubdomain ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::edit_setup` : `${this.suinsClient.config.subNamesPackageId}::subdomains::edit_setup`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(parentNft),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID),
this.transaction.pure.string((0, import_utils.normalizeSuiNSName)(name, "dot")),
this.transaction.pure.bool(!!allowChildCreation),
this.transaction.pure.bool(!!allowTimeExtension)
]
});
}
/**
* Extends the expiration of a subname.
*/
extendExpiration({
nft,
expirationTimestampMs
}) {
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (!this.suinsClient.config.subNamesPackageId)
throw new Error("Subnames package ID not found");
this.transaction.moveCall({
target: `${this.suinsClient.config.subNamesPackageId}::subdomains::extend_expiration`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(nft),
this.transaction.pure.u64(expirationTimestampMs)
]
});
}
/**
* Sets the user data of an NFT.
*/
setUserData({
nft,
value,
key,
isSubname
}) {
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
if (isSubname && !this.suinsClient.config.tempSubdomainsProxyPackageId)
throw new Error("Subnames proxy package ID not found");
if (!Object.values(import_constants.ALLOWED_METADATA).some((x) => x === key)) throw new Error("Invalid key");
this.transaction.moveCall({
target: isSubname ? `${this.suinsClient.config.tempSubdomainsProxyPackageId}::subdomain_proxy::set_user_data` : `${this.suinsClient.config.packageId}::controller::set_user_data`,
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(nft),
this.transaction.pure.string(key),
this.transaction.pure.string(value),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID)
]
});
}
/**
* Burns an expired NFT to collect storage rebates.
*/
burnExpired({ nft, isSubname }) {
if (!this.suinsClient.config.suins) throw new Error("SuiNS Object ID not found");
this.transaction.moveCall({
target: `${this.suinsClient.config.packageId}::controller::${isSubname ? "burn_expired_subname" : "burn_expired"}`,
// Update this
arguments: [
this.transaction.object(this.suinsClient.config.suins),
this.transaction.object(nft),
this.transaction.object(import_utils.SUI_CLOCK_OBJECT_ID)
]
});
}
}
//# sourceMappingURL=suins-transaction.js.map