Typescript API
Simple frontend framework to interface with the NEAR testnet and mainnet smart-contracts
This section is based on Pulse Markets' web client implementation.
You may organize your frontend application in any fashion you'd like. However, Pulse Markets app has 4 vital contract helper classes:

These contract helper classes are used by the contract hooks and ultimately by the React components.
For each NEAR Rust contract in Pulse's contract suite, there's a helper class. These helper classes implement methods that interact directly with a contract.
For example, in order to buy, bet or purchase an outcome from a given market, this method is used by the frontend client:
src/providers/near/contracts/fungible-token/index.ts
static async ftTransferCall(wallet: Wallet, contractAddress: AccountId, args: FtTransferCallArgs) {
try {
const gas = new BN("60000000000000");
const response = await wallet.signAndSendTransactions({
transactions: [
{
receiverId: contractAddress,
actions: [
{
type: "FunctionCall",
params: {
methodName: "ft_transfer_call",
args,
gas: gas.toString(),
deposit: "1",
},
},
],
},
],
});
const [result] = response as Array<FinalExecutionOutcome>;
if ((result?.status as FinalExecutionStatus)?.SuccessValue) {
const value = atob((result.status as FinalExecutionStatus)?.SuccessValue!).replaceAll('"', "");
return value;
}
} catch (error) {
console.log(error);
throw new Error("ERR_FungibleTokenContract_ftTransferCall");
}
return "0.00";
}
From the example above, betting on a market outcome ends up calling the contract class helper method, but to follow best practices, we do this through a React hook.
src/providers/near/contracts/fungible-token/useNearFungibleTokenContract.tsx
const ftTransferCall = async (receiverId: AccountId, amount: string, outcomeId: OutcomeId) => {
try {
assertWalletConnection();
assertContractAddress();
setActions((prev) => ({
...prev,
ftTransferCall: {
...prev.ftTransferCall,
isLoading: true,
},
}));
const msg = JSON.stringify({ BuyArgs: { outcome_id: outcomeId } });
await FungibleTokenContract.ftTransferCall(walletState.context.wallet!, contractAddress!, {
receiver_id: receiverId,
amount,
msg,
});
toast.trigger({
variant: "confirmation",
withTimeout: false,
title: "Your bet was made successfully",
children: (
<Typography.Text>{`Bought ${currency.convert.toDecimalsPrecisionString(amount, metadata?.decimals!)} ${
metadata?.symbol
} of "${marketContractValues?.market.options[outcomeId]}"`}</Typography.Text>
),
});
} catch {
toast.trigger({
variant: "error",
title: "Failed to make transfer call",
children: <Typography.Text>Check your internet connection, connect your wallet and try again.</Typography.Text>,
});
}
setActions((prev) => ({
...prev,
ftTransferCall: {
...prev.ftTransferCall,
isLoading: false,
},
}));
};
From inside a component, you'll call this hook to interact with the contract. This allows you to better handle errors:
src/ui/pulse/swap-card/SwapCard.tsx
const FungibleTokenContract = useNearFungibleTokenContract({ contractAddress: collateralTokenMetadata.id });
// ...
const buy = async (amount: string) => {
if (isOver) {
toast.trigger({
variant: "error",
title: "Market is over",
children: <Typography.Text>Cannot purchase market options on this event.</Typography.Text>,
});
return;
}
await FungibleTokenContract.ftTransferCall(marketId, amount, MarketContract.selectedOutcomeToken!.outcome_id);
updateCollateralTokenBalance();
};
In order to call a NEAR contract, a user must first connect their wallet. A NEAR wallet connection is performed by using the
NearWalletSelectorContextController
.The connected wallet state is then used by the contract hooks and ultimately, by the contract classes.
Notice the use of
useWalletStateContext()
at useNearFungibleTokenContract()
and how walletState.context.wallet!
is passed to ftTransferCall
:src/providers/near/contracts/fungible-token/useNearFungibleTokenContract.tsx
// ..
const walletState = useWalletStateContext();
// ..
const ftTransferCall = async (receiverId: AccountId, amount: string, outcomeId: OutcomeId) => {
try {
// ..
await FungibleTokenContract.ftTransferCall(walletState.context.wallet!, contractAddress!, {
receiver_id: receiverId,
amount,
msg,
});
} catch {
// ..
}
};
Last modified 2mo ago