@silvana-one/nft
Version:
Mina NFT library
334 lines • 11.1 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { AccountUpdate, method, Permissions, PublicKey, State, state, UInt64, SmartContract, Bool, Field, Struct, VerificationKey, } from "o1js";
/**
* The BulletinBoard contract serves as a centralized event emitter for NFT marketplace activities.
* It provides a standardized way to broadcast and track various marketplace events such as:
* - New collection listings
* - Offers made on NFTs
* - Offer cancellations
* - Bids placed on NFTs
* - Bid cancellations
* - Completed sales
*
* While anyone can emit events through this contract, all events are prefixed with "BB_" to
* distinguish them from events emitted directly by NFT contracts. This helps maintain clarity
* in event tracking and marketplace activity monitoring.
*
* The BulletinBoard does not handle any NFT transfers or escrow - it purely exists as an
* event broadcasting mechanism to help indexers and UIs track marketplace activity.
*/
export { BB_NewCollectionEvent, BB_OfferEvent, BB_CancelOfferEvent, BB_BidEvent, BB_CancelBidEvent, BB_SaleEvent, BB_UpgradeVerificationKeyEvent, BB_ChangeAdminEvent, BulletinBoard, };
class BB_NewCollectionEvent extends Struct({
/** The collection address. */
collection: PublicKey,
}) {
}
class BB_OfferEvent extends Struct({
/** The collection address. */
collection: PublicKey,
/** The NFT address. */
nft: PublicKey,
/** The offer address. */
offer: PublicKey,
/** The price. */
price: UInt64,
}) {
}
class BB_CancelOfferEvent extends Struct({
/** The collection address. */
collection: PublicKey,
/** The NFT address. */
nft: PublicKey,
}) {
}
class BB_BidEvent extends Struct({
/** The collection address. */
collection: PublicKey,
/** The NFT address. */
nft: PublicKey,
/** The bid address. */
bid: PublicKey,
/** The price. */
price: UInt64,
}) {
}
class BB_CancelBidEvent extends Struct({
/** The collection address. */
collection: PublicKey,
/** The NFT address. */
nft: PublicKey,
/** The bid address. */
bid: PublicKey,
}) {
}
class BB_SaleEvent extends Struct({
/** The collection address. */
collection: PublicKey,
/** The NFT address. */
nft: PublicKey,
/** The buyer address. */
buyer: PublicKey,
/** The price. */
price: UInt64,
}) {
}
class BB_UpgradeVerificationKeyEvent extends Struct({
/** The new verification key. */
vk: Field,
}) {
}
class BB_ChangeAdminEvent extends Struct({
/** The new admin. */
admin: PublicKey,
}) {
}
/**
* The BulletinBoard contract serves as a centralized event emitter for NFT marketplace activities.
* It provides a standardized way to broadcast and track various marketplace events such as:
* - New collection listings
* - Offers made on NFTs
* - Offer cancellations
* - Bids placed on NFTs
* - Bid cancellations
* - Completed sales
*
* While anyone can emit events through this contract, all events are prefixed with "BB_" to
* distinguish them from events emitted directly by NFT contracts. This helps maintain clarity
* in event tracking and marketplace activity monitoring.
*/
class BulletinBoard extends SmartContract {
constructor() {
super(...arguments);
this.admin = State();
this.fee = State();
this.events = {
newCollection: BB_NewCollectionEvent,
offer: BB_OfferEvent,
cancelOffer: BB_CancelOfferEvent,
bid: BB_BidEvent,
cancelBid: BB_CancelBidEvent,
sale: BB_SaleEvent,
upgradeVerificationKey: BB_UpgradeVerificationKeyEvent,
changeAdmin: BB_ChangeAdminEvent,
withdraw: UInt64,
setFee: UInt64,
};
}
async deploy(args) {
await super.deploy(args);
this.admin.set(args.admin);
this.fee.set(args.fee ?? UInt64.from(100_000_000));
this.account.permissions.set({
...Permissions.default(),
send: Permissions.proof(),
setVerificationKey: Permissions.VerificationKey.proofDuringCurrentVersion(),
setPermissions: Permissions.impossible(),
});
}
/**
* Pays the fee to prevent spamming the BulletinBoard with fake events.
*/
async payFee() {
const fee = this.fee.getAndRequireEquals();
const sender = this.sender.getUnconstrained();
const feeUpdate = AccountUpdate.createSigned(sender);
feeUpdate.body.useFullCommitment = Bool(true); // Prevent memo and fee change
feeUpdate.balance.subInPlace(fee);
this.balance.addInPlace(fee);
return feeUpdate;
}
/**
* Emits a new collection event.
* @param collection - The collection address.
*/
async newCollection(collection) {
await this.payFee();
this.emitEvent("newCollection", new BB_NewCollectionEvent({
collection,
}));
}
/**
* Emits an offer event.
* @param collection - The collection address.
* @param nft - The NFT address.
* @param offer - The offer address.
* @param price - The price.
*/
async offer(collection, nft, offer, price) {
await this.payFee();
this.emitEvent("offer", new BB_OfferEvent({ collection, nft, offer, price }));
}
/**
* Emits a cancel offer event.
* @param collection - The collection address.
* @param nft - The NFT address.
*/
async cancelOffer(collection, nft) {
await this.payFee();
this.emitEvent("cancelOffer", new BB_CancelOfferEvent({ collection, nft }));
}
/**
* Emits a bid event.
* @param collection - The collection address.
* @param nft - The NFT address.
* @param bid - The bid address.
* @param price - The price.
*/
async bid(collection, nft, bid, price) {
await this.payFee();
this.emitEvent("bid", new BB_BidEvent({ collection, nft, bid, price }));
}
/**
* Emits a cancel bid event.
* @param collection - The collection address.
* @param nft - The NFT address.
* @param bid - The bid address.
*/
async cancelBid(collection, nft, bid) {
await this.payFee();
this.emitEvent("cancelBid", new BB_CancelBidEvent({ collection, nft, bid }));
}
/**
* Emits a sale event.
* @param collection - The collection address.
* @param nft - The NFT address.
* @param buyer - The buyer address.
* @param price - The price.
*/
async sale(collection, nft, buyer, price) {
await this.payFee();
this.emitEvent("sale", new BB_SaleEvent({ collection, nft, buyer, price }));
}
/**
* Ensures that the transaction is authorized by the contract owner.
* @returns A signed `AccountUpdate` from the admin.
*/
async ensureOwnerSignature() {
const admin = this.admin.getAndRequireEquals();
const adminUpdate = AccountUpdate.createSigned(admin);
adminUpdate.body.useFullCommitment = Bool(true); // Prevent memo and fee change
return adminUpdate;
}
/**
* Changes the contract's admin
* @param admin - The new admin.
*/
async changeAdmin(admin) {
await this.ensureOwnerSignature();
// Set the new admin
this.admin.set(admin);
// Emit the change admin event
this.emitEvent("changeAdmin", new BB_ChangeAdminEvent({ admin }));
}
/**
* Changes the contract's fee
* @param fee - The new fee.
*/
async setFee(fee) {
await this.ensureOwnerSignature();
// Set the new fee
this.fee.set(fee);
// Emit the change fee event
this.emitEvent("setFee", fee);
}
/**
* Upgrades the contract's verification key after validating with the upgrade authority.
* @param vk - The new verification key to upgrade to.
*/
async upgradeVerificationKey(vk) {
await this.ensureOwnerSignature();
// Set the new verification key
this.account.verificationKey.set(vk);
// Emit the upgrade event
this.emitEvent("upgradeVerificationKey", new BB_UpgradeVerificationKeyEvent({ vk: vk.hash }));
}
/**
* Withdraws the fee by admin
*/
async withdraw(amount) {
const adminUpdate = await this.ensureOwnerSignature();
adminUpdate.balance.addInPlace(amount);
this.balance.subInPlace(amount);
this.emitEvent("withdraw", amount);
}
}
__decorate([
state(PublicKey),
__metadata("design:type", Object)
], BulletinBoard.prototype, "admin", void 0);
__decorate([
state(UInt64),
__metadata("design:type", Object)
], BulletinBoard.prototype, "fee", void 0);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "newCollection", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey,
PublicKey,
PublicKey,
UInt64]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "offer", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey, PublicKey]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "cancelOffer", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey,
PublicKey,
PublicKey,
UInt64]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "bid", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey,
PublicKey,
PublicKey]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "cancelBid", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey,
PublicKey,
PublicKey,
UInt64]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "sale", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [PublicKey]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "changeAdmin", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [UInt64]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "setFee", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [VerificationKey]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "upgradeVerificationKey", null);
__decorate([
method,
__metadata("design:type", Function),
__metadata("design:paramtypes", [UInt64]),
__metadata("design:returntype", Promise)
], BulletinBoard.prototype, "withdraw", null);
//# sourceMappingURL=bb.js.map