Raindrops
Search
K

Manipulate

Update the NFT with the new equipped items.
First we need to prepare the payload to create the transaction for the user to sign.
import { State } from "@raindrops-protocol/raindrops";
enum Action {
Adding,
Removing,
Equipping,
Unequipping,
}
type PlayerManipulatorPayload = {
nftMint: string;
nftHolder: string;
actions: {
itemClassMint: any;
itemMint: any;
parentItemClassMint: web3.PublicKey;
bodyPartIndex: number | undefined;
itemUsageIndex: any;
action: Action;
}[];
};
const getBodyPartIndex = (player: Player, bodyPartName: string) => {
return player.parent.bodyParts.find(
(bodyPart: Omit<BodyPartDetails, "items">) => {
return bodyPart.bodyPart.toLowerCase() === bodyPartName.toLowerCase();
}
)?.index;
};
const getItemUsageIndex = (itemClassData: any, bodyPartName: string) => {
return itemClassData?.itemClassData?.config?.usages?.find(
(usage: State.Item.ItemUsage) =>
usage.itemClassType.wearable &&
usage.itemClassType.wearable.bodyPart.length &&
usage.itemClassType.wearable.bodyPart
.map((x) => x.toLowerCase())
.includes(bodyPartName.toLowerCase())
)?.index;
};
const payload: PlayerManipulatorPayload = {
nftMint: player.mint.toBase58(),
nftHolder: wallet.publicKey.toBase58(),
actions: actions.map(({ item, action }) => ({
itemClassMint: item.itemClassData.mint,
itemMint: item.itemData.mint,
parentItemClassMint: item.parentItemClassMint,
bodyPartIndex: getBodyPartIndex(player, item.bodyPart),
itemUsageIndex: getItemUsageIndex(item.itemClassData, item.bodyPart),
action,
})),
};
Then we send the payload off to the Boots API
const submitResponse = await fetch(
getBootsApiUrl("player-manipulator/manipulate"),
{
method: "POST",
mode: "cors",
body: JSON.stringify(payload),
headers: {
"x-api-key": getBootsAPIKey(),
"Content-Type": "application/json",
"x-stage": getBootsStage(),
},
}
);
const response = await submitResponse.json();
const { licenseState, transactions } = response;
If the resultant licenseState is "SUB_LICENSE_FILLED" the user will not be able to proceed.
If the resultant licenseState is "SUB_LICENSE_AVAILABLE" the user will need to pay the license fee.
However, if the licenseState is "NONE" we can continue to sign the transactions and send a call to the API to update the metadata:
import { State, Utils } from "@raindrops-protocol/raindrops";
import { WalletContextState } from "@solana/wallet-adapter-react";
import { Connection, PublicKey, Transaction } from "@solana/web3.js";
const { sendSignedTransaction, sleep } = Utils.Transactions;
type MetadataManipulatorPayload = {
nftMint: string;
nftHolder: string;
};
const submitRecievedTransactions = async ({
payload,
transactions,
signTransaction,
connection,
}: {
payload?: MetadataManipulatorPayload;
transactions: Transaction[];
signTransaction: NonNullable<WalletContextState["signTransaction"]>;
connection: Connection;
}) => {
const signed = await signTransaction(transactions[0]);
const { txid } = await sendSignedTransaction({
signedTransaction: signed,
connection,
});
if (!txid) {
return { txid };
}
if (payload) {
await sleep(10000);
for (let i = 0; i < 3; i++) {
const response = await fetch(
getBootsApiUrl("metadata-manipulator/manipulate"),
{
method: "POST",
mode: "cors",
body: JSON.stringify(payload),
headers: {
"x-api-key": getBootsAPIKey(),
"Content-Type": "application/json",
"x-stage": getBootsStage(),
},
}
);
if (response.ok) {
const result = await response.json();
if (result.transactionId) {
return { txid: result.transactionId };
}
}
await sleep(15000);
}
throw new Error("Manipulate metadata request error");
}
return { txid };
};