Research
Security News
Malicious npm Package Targets Solana Developers and Hijacks Funds
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
blindbox-sdk
Advanced tools
- [Install](#install) - [Browser with Metamask](#browser-with-metamask) - [Node with Ethers Provider](#node-with-ethers-provider) - [API Reference](#api-reference) - [Interface](#interface) - [MockClient Example](#mockclient-example)
yarn add blindbox-sdk
yarn upgrade blindbox-sdk
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,
ContractBuyResult,
ContractFuseResult,
ContractTokenDetail,
ContractDealDetail,
} from "blindbox-sdk";
const RIVERBOX_CONTRACT_ADDRESS = "0x0f522004467899fcbde46d3dec324e8f3238db14"; // v 0.2.0 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 client : IClient = riverBoxProvider(
// false // mock = true or false
// );
// call read only methods
client.connectProvider(RIVERBOX_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.toNumber() / 1e18, "ETH");
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());
} 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;
JsonRpcProvider or WebSocketProvider or APIProviders:
import { riverBoxProvider, IClient } from 'blindbox-sdk';
import { WebSocketProvider } from '@ethersproject/providers';
import { ethers, Signer, Wallet } from 'ethers';
const CONTRACT_ADDRESS = '0x5FbDB2315678afecb367f032d93F642f64180aa3'; // example
const PRIVATE_KEY =
'0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e';
// https://docs.ethers.io/v5/api/providers/
const provider: WebSocketProvider = new ethers.providers.WebSocketProvider(
'http://localhost:8545'
);
const signer: Wallet = new Wallet(PRIVATE_KEY).connect(provider);
const client: IClient = riverBoxProvider(CONTRACT_ADDRESS, provider, signer);
const client = await client.symbol();
// console> RB
export interface IBuyResult {
transactionHash: string;
newTokenIds: BigNumber[];
}
export interface IFuseResult {
transactionHash: string;
newTokenId: BigNumber;
}
export interface IAwardedBoxEvent {
payer: string;
tokenId: BigNumber;
}
export interface IProductDetail {
locationId: BigNumber;
signature: BigNumber; // item properties hash - uint256
creationTime: BigNumber; // unix time
fused: BigNumber; // number of times used to fuse item
parts: BigNumber[]; // a list of token ids which are used to fuse this item
}
export interface IClient {
connectProvider(address: string, provider: Provider): IClient;
connectSigner(signer: Signer): IClient;
setWaitConfirmations(num: number): void;
/* Backup interface
* @return RiverBox typechain interface for RiverBox contract
*/
contract?(): RiverBox | undefined;
/*======== RiverBox specific ======*/
/* view */
/**
* Return 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
*/
tokenDetails(
tokenId: BigNumber,
config?: PayableOverrides
): Promise<IProductDetail>;
/**
* 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<IBuyResult>;
/**
* 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<IFuseResult>;
/*======== 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>;
/* transactions */
// TODO
}
}
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
yarn run build
Start local hardhat node first and deploy the contract
CONTRACT_ADDRESS={ADDRESS} yarn run test
FAQs
[![npm version](https://badge.fury.io/js/blindbox-sdk.svg)](https://badge.fury.io/js/blindbox-sdk)
The npm package blindbox-sdk receives a total of 9 weekly downloads. As such, blindbox-sdk popularity was classified as not popular.
We found that blindbox-sdk demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
A malicious npm package targets Solana developers, rerouting funds in 2% of transactions to a hardcoded address.
Security News
Research
Socket researchers have discovered malicious npm packages targeting crypto developers, stealing credentials and wallet data using spyware delivered through typosquats of popular cryptographic libraries.
Security News
Socket's package search now displays weekly downloads for npm packages, helping developers quickly assess popularity and make more informed decisions.