Transaction construction
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. Check code.
Create a product:
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 });
}
});
Registering a purchase:
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];
}
Create a marketplace:
I am using a solana playground repo with more scripts calling more Brick program instructions.
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();
Last updated