Galactic Marketplace
Decentralized MMO-style trading
Mainnet Key Label | Program Address |
---|---|
Program ID | traderDnaR5w6Tcoi3NFm53i48FTDNbGjBSZwWXDRrg |
The Galactic Marketplace is a decentralized trading protocol on the Solana blockchain that provides an MMO Auction House experience as a public utility.
At a glance:
- Fast and responsive data
- Fully decentralized peer-to-peer trading through an MMO auction house-style experience
- Easy integration with decentralized applications and protocols
As a user, here are some of the things you're able to do with the Galactic Marketplace:
- Create your own buy and sell orders for any Solana token
- Query, view, and cancel your existing orders
- Buy from and sell into other people's orders
If you're using
GmClientService
to fetch order data, you can expect price
field of an Order
to be the price in base units. Use uiPrice
to retrieve a decimal-adjusted value.import { BN } from 'bn.js';
class Order {
id: string;
orderMint: string;
currencyMint: string;
currencyDecimals: number;
orderOriginationQty: number;
orderQtyRemaining: number;
orderType: OrderSide;
owner: string;
ownerAssetTokenAccount: string;
ownerCurrencyTokenAccount: string;
price: BN;
uiPrice: number;
};
enum OrderSide {
Buy = 'buy',
Sell = 'sell',
}
Any arbitrary
itemMint
can be transacted permissionlessly. This can be any tokenized asset including SFTs and NFTs.There are a limited number of valid
currencyMint
options:Token Symbol | Mainnet Address |
---|---|
ATLAS | ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx |
USDC | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
The
GmClientService
is used to:- Construct Solana transactions to interact with the Galactic Marketplace
- Creating orders
- Canceling orders
- Filling orders
- Fetch metadata about registered currencies
- Fetch lists of open orders for combinations of:
- Specific mints
- User PublicKeys
- Specific currencies
Because the currency information is unlikely to change often this result will be cached for the lifecycle of
GmClientService
to reduce the total number of RPC calls made. If you wish to forcefully refetch this information pass true
as an optional argument into getRegisteredCurrencies()
.import { Connection, PublicKey } from '@solana/web3.js';
import { GmClientService } from '@staratlas/factory';
const connection = new Connection();
const programId = new PublicKey();
const gmClientService = new GmClientService();
const currencyInfo = await gmClientService.getRegisteredCurrencies(
connection,
programId,
false, // or true to invalidate the cache
);
console.log(currencyInfo);
Retrieve a list of all open orders for all currencies and items in the Galactic Marketplace.
import { Connection, PublicKey } from '@solana/web3.js';
import { GmClientService } from '@staratlas/factory';
const connection = new Connection();
const programId = new PublicKey();
const gmClientService = new GmClientService();
const allOrders = await gmpClientService.getAllOpenOrders(connection, programId);
console.log(allOrders);
Create an order for
itemMint
- use orderSide
to specify the direction of the trade.When creating a
Sell
order, the orderCreator
must deposit their itemMint
into escrow and likewise when creating a Buy
order they must deposit their quoteMint
into escrow.import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { GmClientService, OrderSide } from '@staratlas/factory';
import MyWalletService from '../MyWalletService';
const connection = new Connection();
const orderCreator = MyWalletService.publicKey;
const itemMint = new PublicKey();
const quoteMint = new PublicKey();
const quantity = 12;
const uiPrice = 24.187;
const programId = new PublicKey();
const orderSide = OrderSide.Sell; // The user is selling their itemMint and asking for quoteMint
const gmClientService = new GmClientService();
// Note that the price should be a BN which is decimal-adjusted base token units
const price = gmClientService.getBnPriceForCurrency(
connection,
uiPrice,
quoteMint,
programId,
);
const orderTx = await gmClientService.getInitializeOrderTransaction(
connection,
orderCreator
itemMint,
quoteMint,
quantity,
price,
programId,
orderSide,
);
const transactionId = await connection.sendTransaction(
orderTx,
[MyWalletService.wallet],
);
console.log(transactionId);
Note that orders can be partially filled. For example, if a player has an order to buy 10 Pearce X4s a seller can fill 4 out of those 10 while leaving the order open for other users to interact with.
getCreateExchangeTransaction()
will work for both selling into a Buy
order and buying from a Sell
order.import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { GmClientService, Order } from '@staratlas/factory';
import MyWalletService from '../MyWalletService';
const connection = new Connection();
const orderTaker = MyWalletService.publicKey;
const purchaseQty = 4;
const programId = new PublicKey();
const gmClientService = new GmClientService();
const order = gmClientService.getOpenOrder('some_order_id');
const exchangeTx = await gmClientService.getCreateExchangeTransaction(
connection,
order,
orderTaker,
purchaseQty,
programId,
);
const transactionId = await connection.sendTransaction(
exchangeTx,
[MyWalletService.wallet],
);
console.log(transactionId);
Orders can be canceled as long as they are still open, whether they have been partially filled or not. If a partially filled order is canceled, the unfilled portion of the order is returned to the order creator.
import { Connection, PublicKey, Transaction } from '@solana/web3.js';
import { GmClientService, Order } from '@staratlas/factory';
import MyWalletService from '../MyWalletService';
const connection = new Connection();
const programId = new PublicKey();
const gmClientService = new GmClientService();
const order = gmpClientService.getOpenOrder('some_order_id');
const orderAccount = new PublicKey(order.id);
const orderInitializer = MyWalletService.publicKey;
const cancelTx = await gmpClientService.getCreateExchangeTransaction(
connection,
orderAccount,
orderInitializer,
programId,
);
const transactionId = await connection.sendTransaction(
cancelTx,
[MyWalletService.wallet],
);
console.log(transactionId);
Because the marketplace is fully decentralized, the methods on this service will return orders for all items being transacted on the Galactic Marketplace, even items which were not created by Star Atlas.
The
GmOrderbookService
is a read-only data caching layer which maintains a real-time list of all of the open orders on the Galactic Marketplace.import { Connection, PublicKey } from '@solana/web3.js';
import { GmOrderbookService } from '@staratlas/factory';
const programId = new PublicKey();
const connection = new Connection();
const gmOrderbookService = new GmOrderbookService(
connection,
programId,
);
await gmOrderbookService.start();
const allMints: string[] = gmOrderbookService.getAllMints();
console.log(allMints.length);
import { MyWalletService } from '../MyWalletService';
const ordersForMyWallet = gmOrderbookService.getAllOrdersForUserAddress(MyWalletService.publicKey);
console.log(ordersForMyWallet.length);
import { PublicKey } from '@solana/web3.js';
const itemMint = 'DdpXnnYsyUQgJby8TDHbmPwkKyGF4U6bXwCXTQZsrfKP';
const ordersForItemMint = gmOrderbookService.getAllOrdersByItemMint(itemMint);
console.log(ordersForItemMint.length);
Class instances which implement
GmOrderbookService
can register event handlers when the marketplace state changes.If you just need raw event callbacks without maintaining a snapshot of the on-chain marketplace state consider implementing GmEventService instead
import {
GmEventHandler,
GmChangeEvent,
GmEventType,
GmOrderbookService,
} from '@staratlas/factory';
export class MyService implements GmEventHandler {
private gmOrderbookService: GmOrderbookService;
constructor(rpcUrl: string, programId: PublicKey) {
this.gmOrderbookService = new GmOrderbookService(rpcUrl, programId);
// Register this class as an event handler
this.gmOrderbookService.addOnEventHandler(this);
}
// onEvent will be fired any time a change occurs in the marketplace state
onEvent(event: GmChangeEvent): void {
switch(event.eventType) {
case GmEventType.orderAdded:
this.handleOrderAdded(event);
break;
case GmEventType.orderModified:
this.handleOrderModified(event);
break;
case GmEventType.orderRemoved:
this.handleOrderRemoved(event);
break;
default:
break;
}
}
private handleOrderAdded(event: GmChangeEvent): void {
console.log(event.order);
}
private handleOrderModified(event: GmChangeEvent): void {
console.log(event.order);
}
private handleOrderRemoved(event: GmChangeEvent): void {
console.log(event.order);
}
}
The
GmEventService
can be used to trigger an onEvent
callback any time an order is created, modified, or canceled on the Galactic Marketplace.The
GmEventService
is implemented by the GmOrderbookService
and is how its internal state of the marketplace orderbooks is kept up-to-dateimport { Connection, PublicKey } from '@solana/web3.js';
import { GmEventService, GmEventType, Order} from '@staratlas/factory';
const connection = new Connection();
const programId = new PublicKey();
const eventHandler = (
eventType: GmEventType,
order: Order,
slotContext: number,
) => {
console.log(eventType, order, slotContext);
}
const gmEventService = new GmEventService(
connection,
programId,
);
// As events are emitted from the program eventHandler will be called
gmEventService.setEventHandler(eventHandler);
Last modified 7mo ago