Transaction construction
Last updated
Last updated
Most of accounts used by the program are PDAs. The SDK automatically derives these accounts from the provided arguments, reducing the account management.
Presently, my setup involves a server responsible for delivering serialized transactions to the client or application. When the client sends specific parameters through a request, the server responds by providing a pre-built and serialized transaction using the SDK. .
app.get('/initProductTree', async (req: Request, res: Response) => {
try {
if (!rpc) res.status(500).send({error: 'Error: Server rpc not configured'});
const connection = new Connection(rpc);
const { signer, marketplace, paymentMint, params } = req.query;
if (!signer || !marketplace || !paymentMint) {
res.status(500).send({error: 'Error: Missing account'});
}
const accounts = {
signer: new PublicKey(signer),
marketplace: new PublicKey(marketplace),
paymentMint: new PublicKey(paymentMint)
};
const normalizedParams = {
id: String(params.id),
productPrice: Number(params.productPrice),
feeBasisPoints: Number(params.feeBasisPoints),
height: Number(params.height),
buffer: Number(params.buffer),
canopy: Number(params.canopy),
name: String(params.name),
metadataUrl: String(params.metadataUrl),
};
const transaction = await createInitProductTreeTransaction(
connection,
accounts,
normalizedParams
);
res.status(200).send({
transaction: Buffer.from(transaction.serialize()).toString('base64')
});
} catch (error) {
console.log(error)
res.status(500).send({ error: error.message });
}
});
app.get('/registerBuy', async (req: Request, res: Response) => {
try {
if (!rpc) throw new Error('Error: Server rpc not configured');
const connection = new Connection(rpc);
const { signer, marketplace, productId, paymentMint, seller, marketplaceAuth, params } = req.query;
if (!signer || !marketplace || !paymentMint || !productId || !seller || !marketplaceAuth || !params) {
throw new Error('Error: Missing required information');
}
if (!messagesKey) throw new Error('Error: MessagesKey not configured');
const messagesSigner = ImportAccountFromPrivateKey(Uint8Array.from(JSON.parse(messagesKey)));
if (!indexerApi) throw new Error('Error: Indexer server not configured');
const [firstId, secondId] = getSplitId(productId);
const marketKey = new PublicKey(marketplace);
const [product] = PublicKey.findProgramAddressSync(
[
Buffer.from("product", "utf-8"),
firstId,
secondId,
marketKey.toBuffer()
],
BRICK_PROGRAM_ID_PK
);
const productResponse = await queryAccounts(indexerApi, { accounts: [product.toString()] });
const productInfo = productResponse[0].data as Product;
const itemHash = await generateAlephMessage({
product: product.toString(),
seller, signer,
units: Number(params.amount),
paymentMint,
totalAmount: Number(productInfo.sellerConfig.productPrice) * params.amount
}, messagesSigner);
const accounts = {
signer: new PublicKey(signer),
marketplace: new PublicKey(marketplace),
product: new PublicKey(product),
paymentMint: new PublicKey(paymentMint),
seller: new PublicKey(seller),
marketplaceAuth: new PublicKey(marketplaceAuth),
merkleTree: new PublicKey(productInfo.merkleTree),
};
const parsedParams = {
rewardsActive: params.rewardsActive === 'true' ? true : false,
amount: Number(params.amount),
name: params.name,
uri: `https://api1.aleph.im/api/v0/messages.json?hashes=${itemHash}`,
};
const transaction = await createRegisterBuyCnftTransaction(connection, accounts, parsedParams);
res.status(200).send({ transaction: Buffer.from(transaction.serialize()).toString('base64') });
} catch (error) {
res.status(500).send({ error: error.message });
}
});
function getSplitId(str: string): [Buffer, Buffer]{
const bytes = new TextEncoder().encode(str);
const data = new Uint8Array(64);
data.fill(32);
data.set(bytes);
const firstId = Buffer.from(data.slice(0, 32));
const secondId = Buffer.from(data.slice(32));
return [firstId, secondId];
}
With the following script you can create a marketplace:
import { PaymentFeePayer } from "./utils/solita/brick/index.js";
import { Connection, Keypair } from "@solana/web3.js";
import { FNET_MINT } from "./constants.js";
import dotenv from 'dotenv';
import { createInitMarketplaceTransaction } from "brick-protocol";
dotenv.config();
async function initMarketplace() {
const rpc = process.env.rpc || '';
if (rpc === '') throw new Error("RPC not found in environment variables.");
const secret = JSON.parse(process.env.secret || '');
if (secret === '') throw new Error("Secret not found in environment variables.");
const secretUint8Array = new Uint8Array(secret);
const signer = Keypair.fromSecretKey(secretUint8Array);
const connection: Connection = new Connection(rpc);
const accounts = {
signer: signer.publicKey,
rewardMint: FNET_MINT,
discountMint: FNET_MINT,
};
const args = {
fee: 100,
feeReduction: 20,
sellerReward: 10,
buyerReward: 10,
useCnfts: true,
deliverToken: false,
transferable: false,
chainCounter: false,
permissionless: false,
rewardsEnabled: false,
feePayer: PaymentFeePayer.Buyer,
};
const transaction = await createInitMarketplaceTransaction(connection, accounts, args);
transaction.sign([signer]);
console.log(transaction)
const txid = await connection.sendTransaction(transaction);
console.log(`https://explorer.solana.com/tx/${txid}?cluster=mainnet`);
}
initMarketplace();
I am using a with more scripts calling more Brick program instructions.