@iota/iota-names-sdk
Version:
IOTA-Names SDK
426 lines (425 loc) • 16.6 kB
JavaScript
import { bcs } from "@iota/iota-sdk/bcs";
import { IOTA_CLOCK_OBJECT_ID, IOTA_TYPE_ARG } from "@iota/iota-sdk/utils";
import { ALLOWED_METADATA } from "./constants.js";
import { isNestedSubname, isSubname } from "./helpers.js";
import { isValidIotaName, normalizeIotaName } from "./utils.js";
class IotaNamesTransaction {
constructor(client, transaction) {
this.iotaNamesClient = client;
this.transaction = transaction;
}
/**
* Registers a name.
*/
async register(params) {
const paymentIntent = this.initRegistration(params.name);
const couponCodes = params.couponCodes;
let discountedPrice = null;
if (couponCodes && couponCodes.length > 0) {
discountedPrice = await this.iotaNamesClient.calculateDiscountedPrice({
coupons: couponCodes,
name: params.name,
years: 1,
isRegistration: true,
address: params.address
});
for (const couponCode of couponCodes) {
this.applyCoupon(couponCode, paymentIntent);
}
}
const amounts = [discountedPrice ?? this.getBasePrice(paymentIntent)];
const payment = this.transaction.splitCoins(this.transaction.object(params.coin), amounts);
const receipt = this.generateReceipt({
paymentIntent,
payment,
coinConfig: params.coinConfig || { type: IOTA_TYPE_ARG }
});
return this.finalizeRegister(receipt);
}
/**
* Registers a name for a given amount of years.
*/
async registerWithYears(params) {
const paymentIntent = this.initRegistrationWithYears(params.name, params.years);
const couponCodes = params.couponCodes;
let discountedPrice = null;
if (couponCodes && couponCodes.length > 0) {
discountedPrice = await this.iotaNamesClient.calculateDiscountedPrice({
coupons: couponCodes,
name: params.name,
years: params.years,
isRegistration: true,
address: params.address
});
for (const couponCode of couponCodes) {
this.applyCoupon(couponCode, paymentIntent);
}
}
const amounts = [discountedPrice ?? this.getBasePrice(paymentIntent)];
const payment = this.transaction.splitCoins(this.transaction.object(params.coin), amounts);
const receipt = this.generateReceipt({
paymentIntent,
payment,
coinConfig: params.coinConfig || { type: IOTA_TYPE_ARG }
});
return this.finalizeRegister(receipt);
}
/**
* Renews an NFT for a number of years.
*/
async renew(params) {
const paymentIntent = this.initRenewal(params.nft, params.years);
const couponCodes = params.couponCodes;
let discountedPrice = null;
if (couponCodes && couponCodes.length > 0) {
discountedPrice = await this.iotaNamesClient.calculateDiscountedPrice({
coupons: couponCodes,
name: params.name,
years: params.years,
isRegistration: false,
address: params.address
});
for (const couponCode of couponCodes) {
this.applyCoupon(couponCode, paymentIntent);
}
}
const amounts = [discountedPrice ?? this.getBasePrice(paymentIntent)];
const payment = this.transaction.splitCoins(this.transaction.object(params.coin), amounts);
const receipt = this.generateReceipt({
paymentIntent,
payment,
coinConfig: params.coinConfig || { type: IOTA_TYPE_ARG }
});
this.finalizeRenew(receipt, params.nft);
}
initRegistration(name) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = this.iotaNamesClient.getPackage("packageId");
return this.transaction.moveCall({
target: `${packageId}::payment::init_registration`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.pure.string(name)
]
});
}
initRegistrationWithYears(name, years) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = this.iotaNamesClient.getPackage("packageId");
return this.transaction.moveCall({
target: `${packageId}::payment::init_registration_with_years`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.pure.string(name),
this.transaction.pure.u8(years)
]
});
}
initRenewal(nft, years) {
const packageId = this.iotaNamesClient.getPackage("packageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
return this.transaction.moveCall({
target: `${packageId}::payment::init_renewal`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.pure.u8(years)
]
});
}
handleBasePayment(paymentIntent, payment, paymentType) {
const paymentsPackageId = this.iotaNamesClient.getPackage("paymentsPackageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
return this.transaction.moveCall({
target: `${paymentsPackageId}::payments::handle_base_payment`,
arguments: [this.transaction.object(iotaNamesObjectId), paymentIntent, payment],
typeArguments: [paymentType]
});
}
finalizeRegister(receipt) {
const packageId = this.iotaNamesClient.getPackage("packageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
return this.transaction.moveCall({
target: `${packageId}::payment::register`,
arguments: [
receipt,
this.transaction.object(iotaNamesObjectId),
this.transaction.object.clock()
]
});
}
finalizeRenew(receipt, nft) {
const packageId = this.iotaNamesClient.getPackage("packageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
return this.transaction.moveCall({
target: `${packageId}::payment::renew`,
arguments: [
receipt,
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.object.clock()
]
});
}
getBasePrice(paymentIntent) {
const packageId = this.iotaNamesClient.getPackage("packageId");
return this.transaction.moveCall({
target: `${packageId}::payment::request_base_amount`,
arguments: [paymentIntent]
});
}
applyCoupon(couponCode, paymentIntent) {
const couponsPackageId = this.iotaNamesClient.getPackage("couponsPackageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
return this.transaction.moveCall({
target: `${couponsPackageId}::coupon_house::apply_coupon`,
arguments: [
paymentIntent,
this.transaction.object(iotaNamesObjectId),
this.transaction.pure.string(couponCode),
this.transaction.object(IOTA_CLOCK_OBJECT_ID)
]
});
}
generateReceipt(params) {
const receipt = this.handleBasePayment(
params.paymentIntent,
params.payment,
params.coinConfig.type
);
return receipt;
}
/**
* Creates a subname.
*/
createSubname({
parentNft,
name,
expirationTimestampMs,
allowChildCreation,
allowTimeExtension
}) {
if (!isValidIotaName(name)) throw new Error("Invalid IOTA names");
const isParentSubname = isNestedSubname(name);
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const subnamesPackageId = !isParentSubname ? this.iotaNamesClient.getPackage("subnamesPackageId") : null;
const tempSubnameProxyPackageId = isParentSubname ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
const subNft = this.transaction.moveCall({
target: isParentSubname ? `${tempSubnameProxyPackageId}::subname_proxy::new` : `${subnamesPackageId}::subnames::new`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(parentNft),
this.transaction.object(IOTA_CLOCK_OBJECT_ID),
this.transaction.pure.string(normalizeIotaName(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 subname.
* Parent can be a `NameRegistration` or a `SubnameRegistration` object.
* Can be passed in as an ID or a TransactionArgument.
*/
createLeafSubname({
parentNft,
name,
targetAddress
}) {
if (!isValidIotaName(name)) throw new Error("Invalid IOTA names");
const isParentSubname = isNestedSubname(name);
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const subnamesPackageId = !isParentSubname ? this.iotaNamesClient.getPackage("subnamesPackageId") : null;
const tempSubnameProxyPackageId = isParentSubname ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
this.transaction.moveCall({
target: isParentSubname ? `${tempSubnameProxyPackageId}::subname_proxy::new_leaf` : `${subnamesPackageId}::subnames::new_leaf`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(parentNft),
this.transaction.object(IOTA_CLOCK_OBJECT_ID),
this.transaction.pure.string(normalizeIotaName(name, "dot")),
this.transaction.pure.address(targetAddress)
]
});
}
/**
* Removes a leaf subname.
*/
removeLeafSubname({ parentNft, name }) {
if (!isValidIotaName(name)) throw new Error("Invalid IOTA names");
const isParentSubname = isNestedSubname(name);
if (!isSubname(name)) throw new Error("This can only be invoked for subnames");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const subnamesPackageId = !isParentSubname ? this.iotaNamesClient.getPackage("subnamesPackageId") : null;
const tempSubnameProxyPackageId = isParentSubname ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
this.transaction.moveCall({
target: isParentSubname ? `${tempSubnameProxyPackageId}::subname_proxy::remove_leaf` : `${subnamesPackageId}::subnames::remove_leaf`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(parentNft),
this.transaction.object(IOTA_CLOCK_OBJECT_ID),
this.transaction.pure.string(normalizeIotaName(name, "dot"))
]
});
}
/**
* Sets the target address of an NFT.
*/
setTargetAddress({
nft,
// Can be string or argument
address,
isSubname: isSubname2
}) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = !isSubname2 ? this.iotaNamesClient.getPackage("packageId") : null;
const tempSubnameProxyPackageId = isSubname2 ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
this.transaction.moveCall({
target: isSubname2 ? `${tempSubnameProxyPackageId}::subname_proxy::set_target_address` : `${packageId}::controller::set_target_address`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.pure(bcs.option(bcs.Address).serialize(address).toBytes()),
this.transaction.object(IOTA_CLOCK_OBJECT_ID)
]
});
}
/**
* Sets a public name for the user.
*/
setPublic(name) {
if (!isValidIotaName(name)) throw new Error("Invalid IOTA names");
const packageId = this.iotaNamesClient.getPackage("packageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
this.transaction.moveCall({
target: `${packageId}::controller::set_reverse_lookup`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.pure.string(normalizeIotaName(name, "dot"))
]
});
}
/**
* Unsets a Public name for the user.
*/
unsetPublic() {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = this.iotaNamesClient.getPackage("packageId");
this.transaction.moveCall({
target: `${packageId}::controller::unset_reverse_lookup`,
arguments: [this.transaction.object(iotaNamesObjectId)]
});
}
/**
* Edits the setup of a subname.
*/
editSetup({
parentNft,
name,
allowChildCreation,
allowTimeExtension
}) {
if (!isValidIotaName(name)) throw new Error("Invalid IOTA names");
const isParentSubname = isNestedSubname(name);
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const subnamesPackageId = !isParentSubname ? this.iotaNamesClient.getPackage("subnamesPackageId") : null;
const tempSubnameProxyPackageId = isParentSubname ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
this.transaction.moveCall({
target: isParentSubname ? `${tempSubnameProxyPackageId}::subname_proxy::edit_setup` : `${subnamesPackageId}::subnames::edit_setup`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(parentNft),
this.transaction.object(IOTA_CLOCK_OBJECT_ID),
this.transaction.pure.string(normalizeIotaName(name, "dot")),
this.transaction.pure.bool(!!allowChildCreation),
this.transaction.pure.bool(!!allowTimeExtension)
]
});
}
/**
* Extends the expiration of a subname.
*/
extendExpiration({
nft,
expirationTimestampMs
}) {
const subnamesPackageId = this.iotaNamesClient.getPackage("subnamesPackageId");
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
this.transaction.moveCall({
target: `${subnamesPackageId}::subnames::extend_expiration`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.pure.u64(expirationTimestampMs)
]
});
}
/**
* Sets the user data of an NFT.
*/
setUserData({
nft,
value,
key,
isSubname: isSubname2
}) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = !isSubname2 ? this.iotaNamesClient.getPackage("packageId") : null;
const tempSubnameProxyPackageId = isSubname2 ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
if (!Object.values(ALLOWED_METADATA).some((x) => x === key)) throw new Error("Invalid key");
this.transaction.moveCall({
target: isSubname2 ? `${tempSubnameProxyPackageId}::subname_proxy::set_user_data` : `${packageId}::controller::set_user_data`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.pure.string(key),
this.transaction.pure.string(value),
this.transaction.object(IOTA_CLOCK_OBJECT_ID)
]
});
}
/**
* Unsets the user data of an NFT.
*/
unsetUserData({
nft,
key,
isSubname: isSubname2
}) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = !isSubname2 ? this.iotaNamesClient.getPackage("packageId") : null;
const tempSubnameProxyPackageId = isSubname2 ? this.iotaNamesClient.getPackage("tempSubnameProxyPackageId") : null;
if (!Object.values(ALLOWED_METADATA).some((x) => x === key)) throw new Error("Invalid key");
this.transaction.moveCall({
target: isSubname2 ? `${tempSubnameProxyPackageId}::subname_proxy::unset_user_data` : `${packageId}::controller::unset_user_data`,
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.pure.string(key),
this.transaction.object(IOTA_CLOCK_OBJECT_ID)
]
});
}
/**
* Burns an expired NFT to collect storage rebates.
*/
burnExpired({ nft, isSubname: isSubname2 }) {
const iotaNamesObjectId = this.iotaNamesClient.getPackage("iotaNamesObjectId");
const packageId = this.iotaNamesClient.getPackage("packageId");
this.transaction.moveCall({
target: `${packageId}::controller::${isSubname2 ? "burn_expired_subname" : "burn_expired"}`,
// Update this
arguments: [
this.transaction.object(iotaNamesObjectId),
this.transaction.object(nft),
this.transaction.object(IOTA_CLOCK_OBJECT_ID)
]
});
}
}
export {
IotaNamesTransaction
};
//# sourceMappingURL=iota-names-transaction.js.map