Skip to content

Instantly share code, notes, and snippets.

@WietseWind
Last active November 24, 2023 15:28
Show Gist options
  • Save WietseWind/96ab2c11eec2e681d142144b66896327 to your computer and use it in GitHub Desktop.
Save WietseWind/96ab2c11eec2e681d142144b66896327 to your computer and use it in GitHub Desktop.
XLS20 NFToken ID calculation with fixNFTokenRemint compatibility
/// Based on: https://gist.github.com/N3TC4T/a20fb528931ed009ebdd708be4938748
import { derive, utils, signAndSubmit, } from "xrpl-accountlib"
import { XrplClient } from "xrpl-client"
import { decodeAccountID } from "ripple-address-codec"
import { TxData } from 'xrpl-txdata'
// const wss = [ 'wss://testnet.xrpl-labs.com', 'wss://s.altnet.rippletest.net:51233', ]
const wss = [ 'wss://s.devnet.rippletest.net:51233/' ]
const client = new XrplClient(wss)
const account = derive.familySeed("sxxxxxxxx")
const networkInfo = await utils.txNetworkAndAccountValues(client, account)
const tx = {
TransactionType: "NFTokenMint",
TransferFee: 314,
NFTokenTaxon: 0,
Flags: 8,
URI: "697066733A2F2F62616679626569676479727A74357366703775646D37687537367568377932366E6634646675796C71616266336F636C67747179353566627A6469",
Memos: [
{
Memo: {
MemoType: "687474703A2F2F6578616D706C652E636F6D2F6D656D6F2F67656E65726963",
MemoData: "72656E74"
}
}
],
...networkInfo.txValues,
NetworkID: undefined,
}
const submitted = await signAndSubmit(tx, client, account)
console.log(submitted)
client.close()
const txd = new TxData(wss, { AllowNoFullHistory: true, })
const finishedTx = await txd.getOne(submitted.tx_id)
console.log(finishedTx)
////////////////////////////////////
const getTokenID = ({ transaction: { Account, Issuer, NFTokenTaxon, TransferFee, Flags }, meta }) => {
let TokenSequence;
let NextTokenSequence;
let FirstNFTokenSequence;
meta.AffectedNodes.forEach((node) => {
if (
node.ModifiedNode &&
node.ModifiedNode.LedgerEntryType === "AccountRoot"
) {
const { PreviousFields, FinalFields } = node.ModifiedNode;
if (PreviousFields && FinalFields && FinalFields.Account === (Issuer || Account)) {
TokenSequence = PreviousFields.MintedNFTokens;
NextTokenSequence = FinalFields.MintedNFTokens;
FirstNFTokenSequence = PreviousFields?.FirstNFTokenSequence || FinalFields?.FirstNFTokenSequence;
}
}
});
// First minted token, set token sequence to zero
if (typeof TokenSequence === "undefined" && NextTokenSequence === 1) {
TokenSequence = 0;
}
TokenSequence += FirstNFTokenSequence ?? 0
// Unable to find TokenSequence
if (typeof TokenSequence === "undefined") {
throw new Error("Unable to find Token Sequnce");
}
const _Issuer = decodeAccountID(Issuer || Account);
const CipheredTaxon = NFTokenTaxon ^ (384160001 * TokenSequence + 2459);
const TokenID = Buffer.concat([
Buffer.from([(Flags >> 8) & 0xff, Flags & 0xff]),
Buffer.from([(TransferFee >> 8) & 0xff, TransferFee & 0xff]),
_Issuer,
Buffer.from([
(CipheredTaxon >> 24) & 0xff,
(CipheredTaxon >> 16) & 0xff,
(CipheredTaxon >> 8) & 0xff,
CipheredTaxon & 0xff,
]),
Buffer.from([
(TokenSequence >> 24) & 0xff,
(TokenSequence >> 16) & 0xff,
(TokenSequence >> 8) & 0xff,
TokenSequence & 0xff,
]),
]);
// should be 32 bytes
if (TokenID.length !== 32) {
throw new Error("Invalid token id lenght");
}
return TokenID.toString('hex').toUpperCase();
}
////////////////////////////////////
const tokenID = getTokenID(finishedTx.result)
console.log(tokenID)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment