blindbox-sdk
v0.4.0
Published
[![npm version](https://badge.fury.io/js/blindbox-sdk.svg)](https://badge.fury.io/js/blindbox-sdk)
Downloads
66
Readme
SDK Package
Install
yarn add blindbox-sdk
yarn upgrade blindbox-sdk
Browser with Metamask
import React from "react";
import logo from "./logo.svg";
import "./App.css";
import { BigNumber, ethers, Signer } from "ethers";
import { Web3Provider } from "@ethersproject/providers";
import detectEthereumProvider from "@metamask/detect-provider";
import {
riverBoxProvider,
RiverBoxClient,
RiverBoxExClient,
ContractBuyResult,
ContractFuseResult,
ContractTokenDetail,
ContractDealDetail,
riverBoxExProvider,
} from "blindbox-sdk";
const RIVERBOX_CONTRACT_ADDRESS = "0x2Fc70F46000eC3Ea67aDBd701068dB82616F4772"; // v 0.3.0 contract deployed on BSC-Testnet
const RIVERBOX_EX_CONTRACT_ADDRESS = "0x0AA6f3C6Add473628D60F1f87B186D041dc15b62"; // v 0.1.0 exchange contract deployed on BSC-Testnet
function App() {
const [sym, setSym] = React.useState("");
// eslint-disable-next-line react-hooks/exhaustive-deps
React.useEffect(() => {
const fetchSym = async () => {
const winProvider: any = await detectEthereumProvider();
if (winProvider) {
const provider: Web3Provider = new ethers.providers.Web3Provider(
winProvider as any
);
// onchain client
const client: RiverBoxClient = riverBoxProvider(false);
const exClient: RiverBoxExClient = riverBoxExProvider(false);
// call read only methods
client.connectProvider(RIVERBOX_CONTRACT_ADDRESS, provider);
exClient.connectProvider(RIVERBOX_EX_CONTRACT_ADDRESS, provider);
try {
console.log(await provider.getSigner().getAddress());
} catch (error) {
// throw error when no account is connected
console.log(error);
}
try {
const sym = (await client.symbol()) + (await client.totalSupply());
setSym(sym);
console.log(sym);
} catch (error) {
console.log(error);
}
// sand transaction requires a void signer
client.setWaitConfirmations(1); // set number of confirmations to wait default is 5 blocks
await winProvider.request({ method: "eth_requestAccounts" }); // metamask API - ask for connecting an account
console.log(await provider.getSigner().getAddress());
const signer: Signer = provider.getSigner();
try {
const currentPrice = await client.connectSigner(signer).boxPrice();
console.log("currentPrice:", currentPrice.toString(), "wei");
const ret: ContractBuyResult = await client
.connectSigner(signer)
.buy(BigNumber.from(10), { value: currentPrice.mul(10) });
console.log(ret);
const currentPaidBoxes = await client
.connectSigner(signer)
.paidBoxes(await signer.getAddress());
console.log("currentPaidBoxes:", currentPaidBoxes.toString());
// post a deal
const tokenId = ret.newTokenIds[0];
const postDealResult = await exClient.connectSigner(signer).postDeal(tokenId, currentPrice.mul(2))
console.log(postDealResult);
} catch (error) {
console.log(error);
}
}
};
fetchSym();
}, []);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React {sym}
</a>
</header>
</div>
);
}
export default App;
Node with Ethers Provider
JsonRpcProvider or WebSocketProvider or APIProviders: Use low-level etherjs contract interface directly
import {
RiverBox,
RiverBox__factory,
RiverBoxExchange,
RiverBoxExchange__factory,
} from "blindbox-sdk";
import { JsonRpcProvider } from "@ethersproject/providers";
import { ethers, Signer, Wallet } from "ethers";
const RIVERBOX_CONTRACT_ADDRESS = "0x2Fc70F46000eC3Ea67aDBd701068dB82616F4772"; // v 0.3.0 contract deployed on BSC-Testnet
const RIVERBOX_EX_CONTRACT_ADDRESS =
"0x0AA6f3C6Add473628D60F1f87B186D041dc15b62"; // v 0.2.0 exchange contract deployed on BSC-Testnet
const PRIVATE_KEY =
"c1c9223e46ba4b7e3c5bc221fa92cba079999f853d6fb683b95579007fd8c873";
const provider: JsonRpcProvider = new ethers.providers.JsonRpcProvider(
"https://data-seed-prebsc-1-s1.binance.org:8545/"
);
const signer: Wallet = new Wallet(PRIVATE_KEY).connect(provider);
async function main() {
const riverBox: RiverBox = RiverBox__factory.connect(
RIVERBOX_CONTRACT_ADDRESS,
signer
);
console.log(`total balance ${await riverBox.totalSupply()}`);
const riverBoxEx: RiverBoxExchange = RiverBoxExchange__factory.connect(
RIVERBOX_EX_CONTRACT_ADDRESS,
signer
);
console.log(`total deals ${await riverBoxEx.totalDeals()}`);
}
main();
API Reference:
Interface
RiverBox Interface
export interface RiverBoxClient {
connectProvider(address: string, provider: Provider): RiverBoxClient;
connectSigner(signer: Signer): RiverBoxClient;
setWaitConfirmations(num: number): void;
/* Backup interface
* @return RiverBox typechain interface for RiverBox contract
*/
riverBoxContract?(): Promise<RiverBox>;
/*======== RiverBox specific ======*/
/* view */
/**
* Return on current box price
*/
boxPrice(): Promise<BigNumber>;
/**
* Return on chain item detail information
* @param tokenId
* @param config ethers PayableOverrides
* @returns produceDetail on chain item detail data structure
*/
tokenDetail(
tokenId: BigNumber,
config?: PayableOverrides
): Promise<ContractTokenDetail>;
/**
* Verify if a given list of tokenId can be used to fuse a new item
* @param tokenIds list of tokenId
* @param config ethers PayableOverrides
* @return boolean
*/
verifyFusion(
tokenIds: BigNumber[],
config?: PayableOverrides
): Promise<boolean>;
/**
* Fetch tokenIds from a giver owner by index pagination
* @param owner owner address
* @param startIndex
* @param length endIndex = min(startIndex + length, maxLength)
* @param config ethers PayableOverrides
* @return A list of tokenId
*/
tokenOfOwnerByIndexPagination(
owner: string,
startIndex: BigNumber,
length: BigNumber,
config?: PayableOverrides
): Promise<BigNumber[]>;
/**
* Fetch tokenIds from all tokens by index pagination
* @param startIndex
* @param length endIndex = min(startIndex + length, maxLength)
* @param config ethers PayableOverrides
* @return A list of tokenId
*/
tokenOfIndexPagination(
startIndex: BigNumber,
length: BigNumber,
config?: PayableOverrides
): Promise<BigNumber[]>;
/**
* Fetch number of paid boxes
* @param address
* @return number of paid boxes
*/
paidBoxes(account: string, config?: PayableOverrides): Promise<BigNumber>;
/* transactions */
/**
* Buy N boxes (N <= 10 for current setup)
* @param quality number of boxes, will trigger Web3Provider to send transaction in browser
* @param config ethers PayableOverrides
* @return BuyResult including transactionHash and a list of awarded tokenIds
*/
buy(
quality: BigNumber,
config?: PayableOverrides
): Promise<ContractBuyResult>;
/**
* Fuse a set of items
* @param tokenIds a list of tokenId
* @param config ethers PayableOverrides
* @return FuseResult including transactionHash and tokenId of new fused item
*/
fuse(
tokenIds: BigNumber[],
config?: PayableOverrides
): Promise<ContractFuseResult>;
/*======== ERC721 standard API ======*/
/* Refer to https://docs.openzeppelin.com/contracts/3.x/api/token/erc721#ERC721 */
/* view function */
balanceOf(owner: string, config?: PayableOverrides): Promise<BigNumber>;
ownerOf(tokenId: BigNumber, config?: PayableOverrides): Promise<string>;
name(config?: PayableOverrides): Promise<string>;
symbol(config?: PayableOverrides): Promise<string>;
tokenURI(tokenId: BigNumber, config?: PayableOverrides): Promise<string>;
tokenOfOwnerByIndex(
owner: string,
index: BigNumber,
config?: PayableOverrides
): Promise<BigNumber>;
totalSupply(config?: PayableOverrides): Promise<BigNumber>;
tokenByIndex(index: BigNumber, config?: PayableOverrides): Promise<BigNumber>;
}
RiverBoxEx Interface
export interface RiverBoxExClient {
connectProvider(address: string, provider: Provider): RiverBoxExClient;
connectSigner(signer: Signer): RiverBoxExClient;
setWaitConfirmations(num: number): void;
/**
* Backup interface
* @return RiverBox typechain interface for RiverBox contract
*/
contract?(): Promise<RiverBoxExchange>;
/**
* Post a new deal
* @param tokenId
* @param price in BNB wei 18d
* @param config ethers PayableOverrides
* @return ContractPostDealResult {dealId, transactionHash}
*/
postDeal(tokenId: BigNumber, price: BigNumber, config?: PayableOverrides): Promise<ContractPostDealResult>;
/**
* Cancel an existing deal
* @param dealId
* @param config ethers PayableOverrides
* @return transactionHash
*/
cancelDeal(dealId: BigNumber, config?: PayableOverrides): Promise<string>;
/**
* Buy a deal
* @param dealId
* @param config ethers PayableOverrides {value: should >= deal price}
* @return dealId
*/
buyDeal(dealId: BigNumber, config?: PayableOverrides): Promise<string>;
}
MockClient Example
Usage - (MockClient (sdk-mock.spec.ts) output shown by test console output)
(base) ➜ sdk git:(main) ✗ yarn run test
yarn run v1.22.10
$ mocha
RiverBox
view functions
====================================
{
locationId: BigNumber { _hex: '0x01', _isBigNumber: true },
signature: '1111111111111',
creationTime: BigNumber { _hex: '0x0179c141fdd4', _isBigNumber: true },
fused: BigNumber { _hex: '0x00', _isBigNumber: true },
parts: []
}
✓ test: tokenDetails(BigNumber.from(0))
====================================
Mock client: ids.length <= 1 -> false, ids.length > 1 -> true
false
✓ test: verifyFusion([BigNumber.from(0)])
====================================
Mock client: ids.length <= 1 -> false, ids.length > 1 -> true
true
✓ test: verifyFusion([BigNumber.from(0), BigNumber.from(1)])
====================================
[
BigNumber { _hex: '0x64', _isBigNumber: true },
BigNumber { _hex: '0x65', _isBigNumber: true },
BigNumber { _hex: '0x66', _isBigNumber: true },
BigNumber { _hex: '0x67', _isBigNumber: true },
BigNumber { _hex: '0x68', _isBigNumber: true }
]
✓ test: client.tokenOfOwnerByIndexPagination(FAKE_ACCOUNT, BigNumber.from(0), BigNumber.from(5))
====================================
[
BigNumber { _hex: '0x64', _isBigNumber: true },
BigNumber { _hex: '0x65', _isBigNumber: true },
BigNumber { _hex: '0x66', _isBigNumber: true },
BigNumber { _hex: '0x67', _isBigNumber: true },
BigNumber { _hex: '0x68', _isBigNumber: true }
]
✓ test: client.tokenOfIndexPagination(BigNumber.from(0), BigNumber.from(5))
====================================
BigNumber { _hex: '0x64', _isBigNumber: true }
✓ test: client.balanceOf(FAKE_ACCOUNT)
====================================
0x000000000000000000000000000000000000000000
✓ test: client.ownerOf(BigNumber.from(0))
====================================
RiverBox
✓ test: client.name()
====================================
RB
✓ test: client.symbol()
====================================
http://metadata.resolve/0
✓ test: client.tokenURI(BigNumber.from(0))
====================================
BigNumber { _hex: '0x6e', _isBigNumber: true }
✓ test: client.tokenOfOwnerByIndex(FAKE_ACCOUNT, BigNumber.from(10))
====================================
BigNumber { _hex: '0x64', _isBigNumber: true }
✓ test: client.totalSupply()
====================================
BigNumber { _hex: '0x6e', _isBigNumber: true }
✓ test: client.tokenByIndex(BigNumber.from(10))
====================================
✓ clean up
transactions
====================================
{
transactionHash: '0x1111111111111111111111111111111111111111111111111111111111111111',
newTokenIds: [
BigNumber { _hex: '0xc8', _isBigNumber: true },
BigNumber { _hex: '0xc9', _isBigNumber: true },
BigNumber { _hex: '0xca', _isBigNumber: true }
]
}
✓ test: buy(BigNumber.from(3))
====================================
{
transactionHash: '0x1111111111111111111111111111111111111111111111111111111111111111',
newTokenId: BigNumber { _hex: '0xcb', _isBigNumber: true }
}
✓ test: fuse([BigNumber.from(0), BigNumber.from(1)])
====================================
✓ clean up
SDK-Package:
Build:
yarn run build
Test:
Start local hardhat node first and deploy the contract
CONTRACT_ADDRESS={ADDRESS} yarn run test