@polkadot/util#hexToU8a TypeScript Examples
The following examples show how to use
@polkadot/util#hexToU8a.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: util.spec.ts From crust-apps with Apache License 2.0 | 7 votes |
describe('util', (): void => {
it('converts a publicKey to address via publicToAddr', (): void => {
expect(
publicToAddr(
hexToU8a(
'0x836b35a026743e823a90a0ee3b91bf615c6a757e2b60b9e1dc1826fd0dd16106f7bc1e8179f665015f43c6c81f39062fc2086ed849625c06e04697698b21855e'
)
)
).toEqual('0x0BED7ABd61247635c1973eB38474A2516eD1D884');
});
it('converts to valid signature via recoverFromJSON', (): void => {
expect(
JSON.stringify(recoverFromJSON('{"address":"0x002309df96687e44280bb72c3818358faeeb699c","msg":"Pay KSMs to the Kusama account:88dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee","sig":"0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01","version":"2"}'))
).toEqual('{"error":null,"ethereumAddress":"0x002309df96687e44280bb72c3818358faeeb699c","signature":"0x55bd020bdbbdc02de34e915effc9b18a99002f4c29f64e22e8dcbb69e722ea6c28e1bb53b9484063fbbfd205e49dcc1f620929f520c9c4c3695150f05a28f52a01"}');
});
});
Example #2
Source File: utils.ts From gear-js with GNU General Public License v3.0 | 7 votes |
export function getTypesFromTypeDef(
types: Uint8Array | Hex,
registry?: Registry,
): { typesFromTypeDef: any; namespaces: Map<string, string> } {
if (!registry) {
registry = new TypeRegistry();
}
const typesFromTypeDef = {};
const namespaces = new Map<string, string>();
const portableReg = new PortableRegistry(registry, isHex(types) ? hexToU8a(types) : types, true);
portableReg.types.forEach(({ id, type: { path } }) => {
const typeDef = portableReg.getTypeDef(id);
if (path.length === 0 || (!typeDef.lookupName && !typeDef.lookupNameRoot)) {
return;
}
const name = portableReg.getName(id);
let camelCasedNamespace = toCamelCase(path.slice(0, path.length - 1));
if (camelCasedNamespace === name) {
camelCasedNamespace = path.length > 2 ? toCamelCase(path.slice(0, path.length - 2)) : undefined;
}
namespaces.set(name.replace(camelCasedNamespace, ''), name);
typesFromTypeDef[typeDef.lookupName || typeDef.lookupNameRoot] = typeDef.type.toString();
});
return { typesFromTypeDef, namespaces };
}
Example #3
Source File: runner.ts From polkadot-launch with MIT License | 6 votes |
async function generateNodeKeys(
config: ResolvedLaunchConfig
): Promise<string[]> {
var bootnodes = [];
for (const node of config.relaychain.nodes) {
if (!node.nodeKey) {
node.nodeKey = hexStripPrefix(randomAsHex(32));
}
let pair = await libp2pKeys.generateKeyPairFromSeed(
"Ed25519",
hexToU8a(hexAddPrefix(node.nodeKey!)),
1024
);
let peerId: PeerId = await PeerId.createFromPrivKey(pair.bytes);
bootnodes.push(
`/ip4/127.0.0.1/tcp/${node.port}/p2p/${peerId.toB58String()}`
);
}
return bootnodes;
}
Example #4
Source File: InputFile.tsx From crust-apps with Apache License 2.0 | 6 votes |
function convertResult (result: ArrayBuffer): Uint8Array {
const data = new Uint8Array(result);
// this converts the input (if detected as hex), via the hex conversion route
if (data[0] === BYTE_STR_0 && data[1] === BYTE_STR_X) {
let hex = u8aToString(data);
while (hex[hex.length - 1] === STR_NL) {
hex = hex.substr(0, hex.length - 1);
}
if (isHex(hex)) {
return hexToU8a(hex);
}
}
return data;
}
Example #5
Source File: CreateType.ts From gear-js with GNU General Public License v3.0 | 6 votes |
/**
* @deprecated use `decodeHexTypes`
*/
export function parseHexTypes(hexTypes: string) {
let { typesFromTypeDef, namespaces } = getTypesFromTypeDef(hexToU8a(hexTypes));
const result = {};
namespaces.forEach((value, key) => {
const replaced = replaceNamespaces(typesFromTypeDef[value], namespaces);
result[key] = isJSON(replaced) ? JSON.parse(replaced) : replaced;
});
return result;
}
Example #6
Source File: SingleAccountSigner.ts From interbtc-api with Apache License 2.0 | 6 votes |
public async signRaw ({ address, data }: SignerPayloadRaw): Promise<SignerResult> {
if (address !== this.#keyringPair.address) {
throw new Error("does not have the keyringPair");
}
return new Promise((resolve): void => {
setTimeout((): void => {
const signature = u8aToHex(this.#keyringPair.sign(hexToU8a(data)));
resolve({
id: ++id,
signature
});
}, this.#signDelay);
});
}
Example #7
Source File: is-valid-polkadot-address.ts From interbtc-ui with Apache License 2.0 | 6 votes |
isValidPolkadotAddress = (address: string): boolean => {
try {
encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));
return true;
} catch {
return false;
}
}
Example #8
Source File: InputFile.tsx From contracts-ui with GNU General Public License v3.0 | 6 votes |
function convertResult(result: ArrayBuffer): Uint8Array {
const data = new Uint8Array(result);
// this converts the input (if detected as hex), via the hex conversion route
if (data[0] === BYTE_STR_0 && data[1] === BYTE_STR_X) {
let hex = u8aToString(data);
while (hex[hex.length - 1] === STR_NL) {
hex = hex.substr(0, hex.length - 1);
}
if (isHex(hex)) {
return hexToU8a(hex);
}
}
return data;
}
Example #9
Source File: sign.ts From metamask-snap-polkadot with Apache License 2.0 | 6 votes |
export async function signPayloadRaw(
wallet: Wallet, api: ApiPromise, payload: SignerPayloadRaw
): Promise<{ signature: string }|void> {
// ask for confirmation
const confirmation = await showConfirmationDialog(
wallet,
`Do you want to sign following message: \n "${payload.data}" \n with account ${payload.address}`
);
// return seed if user confirmed action
if (confirmation) {
const keyPair = await getKeyPair(wallet);
const signedBytes = keyPair.sign(hexToU8a(payload.data));
return {
signature: u8aToHex(signedBytes)
};
}
}
Example #10
Source File: account.ts From sdk with Apache License 2.0 | 6 votes |
/**
* Get svg icons of pubKeys.
*/
async function genPubKeyIcons(pubKeys: string[]) {
const icons = await genIcons(pubKeys.map((key) => keyring.encodeAddress(hexToU8a(key), 2)));
return icons.map((i, index) => {
i[0] = pubKeys[index];
return i;
});
}
Example #11
Source File: InputFile.tsx From subscan-multisig-react with Apache License 2.0 | 6 votes |
function convertResult(result: ArrayBuffer): Uint8Array {
const data = new Uint8Array(result);
// this converts the input (if detected as hex), via the hex conversion route
if (data[0] === BYTE_STR_0 && data[1] === BYTE_STR_X) {
let hex = u8aToString(data);
while (hex[hex.length - 1] === STR_NL) {
hex = hex.substr(0, hex.length - 1);
}
if (isHex(hex)) {
return hexToU8a(hex);
}
}
return data;
}
Example #12
Source File: address.ts From bodhi.js with Apache License 2.0 | 6 votes |
computeDefaultSubstrateAddress = (evmAddress: string): string => {
if (!isEvmAddress(evmAddress)) {
return logger.throwArgumentError('invalid evm address', 'address', evmAddress);
}
const address = encodeAddress(u8aFixLength(u8aConcat('evm:', hexToU8a(evmAddress)), 256, true));
return address.toString();
}
Example #13
Source File: account.test.ts From metamask-snap-polkadot with Apache License 2.0 | 6 votes |
describe('Test account function: getKeyPair', function() {
const walletStub = new WalletMock();
afterEach(function() {
walletStub.reset();
});
it('should return keypair', async function() {
walletStub.getPluginState.returns({polkadot: {configuration: westendConfiguration}});
walletStub.getAppKey.returns(testAppKey);
walletStub.updatePluginState.returnsArg(0);
const result = await getKeyPair(walletStub);
expect(walletStub.getAppKey).to.have.been.calledOnce;
expect(result.address).to.be.eq(testAddress);
expect(result.publicKey).to.be.deep.eq(hexToU8a(testPublicKey));
});
});
Example #14
Source File: test-precompile-local-assets-erc20.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeDevMoonbeamAllEthTxTypes(
"Precompiles - Assets-ERC20 Wasm",
(context) => {
let sudoAccount, baltatharAccount, assetId, iFace, assetAddress;
before("Setup contract and mock balance", async () => {
const keyring = new Keyring({ type: "ethereum" });
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
baltatharAccount = await keyring.addFromUri(BALTATHAR_PRIV_KEY, null, "ethereum");
// registerAsset
const { events: eventsRegister } = await createBlockWithExtrinsic(
context,
sudoAccount,
context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.assetManager.registerLocalAsset(
baltatharAccount.address,
baltatharAccount.address,
true,
new BN(1)
)
)
);
// Look for assetId in events
eventsRegister.forEach((e) => {
if (e.section.toString() === "assetManager") {
assetId = e.data[0].toHex();
}
});
assetId = assetId.replace(/,/g, "");
assetAddress = u8aToHex(new Uint8Array([...hexToU8a("0xFFFFFFFE"), ...hexToU8a(assetId)]));
const contractData = await getCompiled("LocalAssetExtendedErc20Instance");
iFace = new ethers.utils.Interface(contractData.contract.abi);
const { contract, rawTx } = await createContract(context, "LocalAssetExtendedErc20Instance");
const address = contract.options.address;
await context.createBlock({ transactions: [rawTx] });
});
it("allows to set metadata", async function () {
let data = iFace.encodeFunctionData(
// action
"set_metadata",
["Local", "LOC", 12]
);
const tx = await createTransaction(context, {
from: BALTATHAR,
privateKey: BALTATHAR_PRIV_KEY,
value: "0x0",
gas: "0x200000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
});
const block = await context.createBlock({
transactions: [tx],
});
const receipt = await context.web3.eth.getTransactionReceipt(block.txResults[0].result);
expect(receipt.status).to.equal(true);
const metadata = (await context.polkadotApi.query.localAssets.metadata(assetId)) as any;
expect(u8aToString(metadata.name)).to.eq("Local");
expect(u8aToString(metadata.symbol)).to.eq("LOC");
expect(metadata.decimals.toString()).to.eq("12");
});
},
true
);
Example #15
Source File: Provider.ts From evm-provider.js with Apache License 2.0 | 5 votes |
async _toAddress(addressOrName: string | Promise<string>): Promise<string> {
const resolved = await addressOrName;
const address = encodeAddress(
u8aFixLength(u8aConcat('evm:', hexToU8a(resolved)), 256, true)
);
return address.toString();
}
Example #16
Source File: QrSigner.ts From sdk with Apache License 2.0 | 5 votes |
export function makeTx(api: ApiPromise, txInfo: any, paramList: any[], ss58: number) {
return new Promise((resolve) => {
const signer = txInfo.proxy ? encodeAddress(hexToU8a(txInfo.proxy.pubKey), ss58) : txInfo.sender.address;
api.derive.tx
.signingInfo(signer)
.then(async ({ header, mortalLength, nonce }) => {
let tx: SubmittableExtrinsic<"promise">;
// wrap tx with council.propose for treasury propose
if (txInfo.txName == "treasury.approveProposal") {
tx = await gov.makeTreasuryProposalSubmission(api, paramList[0], false);
} else if (txInfo.txName == "treasury.rejectProposal") {
tx = await gov.makeTreasuryProposalSubmission(api, paramList[0], true);
} else {
tx = api.tx[txInfo.module][txInfo.call](...paramList);
}
// wrap tx with recovery.asRecovered for proxy tx
if (txInfo.proxy) {
tx = api.tx.recovery.asRecovered(txInfo.sender.address, tx);
}
const signerPayload = api.registry.createType("SignerPayload", {
address: signer,
blockHash: header.hash,
blockNumber: header ? header.number : 0,
era: api.registry.createType("ExtrinsicEra", {
current: header.number,
period: mortalLength,
}),
genesisHash: api.genesisHash,
method: tx.method,
nonce,
signedExtensions: ["CheckNonce"],
tip: txInfo.tip,
runtimeVersion: {
specVersion: api.runtimeVersion.specVersion,
transactionVersion: api.runtimeVersion.transactionVersion,
},
version: api.extrinsicVersion,
});
const payload = signerPayload.toPayload();
// limit size of the transaction
const qrIsHashed = payload.method.length > 5000;
const wrapper = api.registry.createType("ExtrinsicPayload", payload, {
version: payload.version,
});
const qrPayload = qrIsHashed ? blake2AsU8a(wrapper.toU8a(true)) : wrapper.toU8a();
// cache this submittableExtrinsic
submittable = {
tx,
payload: signerPayload.toPayload(),
};
// submittable.tx = tx;
// submittable.payload = signerPayload.toPayload();
resolve({
qrAddress: payload.address,
qrIsHashed,
qrPayload: _createFrames(_createSignPayload(payload.address, qrIsHashed ? CMD_HASH : CMD_MORTAL, qrPayload, api.genesisHash))[0],
});
})
.catch((err) => resolve({ error: err.message }));
});
}
Example #17
Source File: test-assets-sufficients.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
async function mockAssetBalance(
context,
assetBalance,
assetDetails,
sudoAccount,
assetId,
account,
is_sufficient
) {
// Register the asset
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.assetManager.registerForeignAsset(
sourceLocationRelayAssetType,
relayAssetMetadata,
new BN(1),
is_sufficient
)
)
.signAndSend(sudoAccount);
await context.createBlock();
let assets = (
(await context.polkadotApi.query.assetManager.assetIdType(assetId)) as any
).toJSON();
// make sure we created it
expect(assets["xcm"]["parents"]).to.equal(1);
// Get keys to modify balance
let module = xxhashAsU8a(new TextEncoder().encode("Assets"), 128);
let account_key = xxhashAsU8a(new TextEncoder().encode("Account"), 128);
let blake2concatAssetId = new Uint8Array([
...blake2AsU8a(assetId.toU8a(), 128),
...assetId.toU8a(),
]);
let blake2concatAccount = new Uint8Array([
...blake2AsU8a(hexToU8a(account), 128),
...hexToU8a(account),
]);
let overallAccountKey = new Uint8Array([
...module,
...account_key,
...blake2concatAssetId,
...blake2concatAccount,
]);
// Get keys to modify total supply
let assetKey = xxhashAsU8a(new TextEncoder().encode("Asset"), 128);
let overallAssetKey = new Uint8Array([...module, ...assetKey, ...blake2concatAssetId]);
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.system.setStorage([
[u8aToHex(overallAccountKey), u8aToHex(assetBalance.toU8a())],
[u8aToHex(overallAssetKey), u8aToHex(assetDetails.toU8a())],
])
)
.signAndSend(sudoAccount);
await context.createBlock();
return;
}
Example #18
Source File: index.ts From parity-bridges-ui with GNU General Public License v3.0 | 5 votes |
export async function getTransactionCallWeight({
action,
account,
targetApi,
transactionState
}: TransactionCallWeightInput) {
let weight: number = 0;
let call: Uint8Array | null = null;
const { receiverAddress, transferAmount, remarkInput, customCallInput, weightInput } = transactionState;
if (account) {
switch (action) {
case TransactionTypes.REMARK:
call = (await targetApi.tx.system.remark(remarkInput)).toU8a();
// TODO [#121] Figure out what the extra bytes are about
logger.info(`system::remark: ${u8aToHex(call)}`);
weight = (await targetApi.tx.system.remark(remarkInput).paymentInfo(account)).weight.toNumber();
break;
case TransactionTypes.TRANSFER:
if (receiverAddress) {
call = (await targetApi.tx.balances.transfer(receiverAddress, transferAmount || 0)).toU8a();
// TODO [#121] Figure out what the extra bytes are about
logger.info(`balances::transfer: ${u8aToHex(call)}`);
logger.info(`after balances::transfer: ${u8aToHex(call)}`);
weight = (
await targetApi.tx.balances.transfer(receiverAddress, transferAmount || 0).paymentInfo(account)
).weight.toNumber();
}
break;
case TransactionTypes.CUSTOM:
if (customCallInput) {
call = isHex(customCallInput) ? hexToU8a(customCallInput.toString()) : null;
weight = parseInt(weightInput!);
}
break;
default:
throw new Error(`Unknown type: ${action}`);
}
}
return { call, weight };
}
Example #19
Source File: Keyring.ts From gear-js with GNU General Public License v3.0 | 5 votes |
static async fromSeed(seed: Uint8Array | string, name?: string): Promise<KeyringPair> {
const keyring = new Keyring({ type: 'sr25519' });
await waitReady();
const keypair = isU8a(seed) ? keyring.addFromSeed(seed, { name }) : keyring.addFromSeed(hexToU8a(seed), { name });
return keypair;
}
Example #20
Source File: test-precompile-local-assets-erc20.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
describeDevMoonbeamAllEthTxTypes(
"Precompiles - Assets-ERC20 Wasm",
(context) => {
let sudoAccount, baltatharAccount, assetId, iFace, assetAddress;
before("Setup contract and mock balance", async () => {
const keyring = new Keyring({ type: "ethereum" });
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
baltatharAccount = await keyring.addFromUri(BALTATHAR_PRIV_KEY, null, "ethereum");
// registerAsset
const { events: eventsRegister } = await createBlockWithExtrinsic(
context,
sudoAccount,
context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.assetManager.registerLocalAsset(
baltatharAccount.address,
baltatharAccount.address,
true,
new BN(1)
)
)
);
// Look for assetId in events
eventsRegister.forEach((e) => {
if (e.section.toString() === "assetManager") {
assetId = e.data[0].toHex();
}
});
assetId = assetId.replace(/,/g, "");
assetAddress = u8aToHex(new Uint8Array([...hexToU8a("0xFFFFFFFE"), ...hexToU8a(assetId)]));
const contractData = await getCompiled("LocalAssetExtendedErc20Instance");
iFace = new ethers.utils.Interface(contractData.contract.abi);
const { contract, rawTx } = await createContract(context, "LocalAssetExtendedErc20Instance");
const address = contract.options.address;
await context.createBlock({ transactions: [rawTx] });
});
it("allows to set team", async function () {
let data = iFace.encodeFunctionData(
// action
"set_team",
[ALITH, ALITH, ALITH]
);
const tx = await createTransaction(context, {
from: BALTATHAR,
privateKey: BALTATHAR_PRIV_KEY,
value: "0x0",
gas: "0x200000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
});
const block = await context.createBlock({
transactions: [tx],
});
const receipt = await context.web3.eth.getTransactionReceipt(block.txResults[0].result);
expect(receipt.status).to.equal(true);
const registeredAsset = (
(await context.polkadotApi.query.localAssets.asset(assetId)) as any
).unwrap();
expect(registeredAsset.admin.toHex()).to.eq(ALITH.toLowerCase());
expect(registeredAsset.freezer.toHex()).to.eq(ALITH.toLowerCase());
expect(registeredAsset.issuer.toHex()).to.eq(ALITH.toLowerCase());
});
},
true
);
Example #21
Source File: Hash.tsx From crust-apps with Apache License 2.0 | 5 votes |
function Hash (): React.ReactElement {
const { t } = useTranslation();
const [{ data, hash, isHexData }, setState] = useState<State>({
data: '',
hash: blake2AsHex(stringToU8a(''), 256),
isHexData: false
});
const _onChangeData = useCallback(
(data: string): void => {
const isHexData = isHex(data);
setState({
data,
hash: blake2AsHex(
isHexData
? hexToU8a(data)
: stringToU8a(data),
256
),
isHexData
});
},
[]
);
return (
<div className='toolbox--Hash'>
<div className='ui--row'>
<Input
autoFocus
className='full'
help={t<string>('The input data to hash. This can be either specified as a hex value (0x-prefix) or as a string.')}
label={t<string>('from the following data')}
onChange={_onChangeData}
value={data}
/>
</div>
<div className='ui--row'>
<Static
className='medium'
help={t<string>('Detection on the input string to determine if it is hex or non-hex.')}
label={t<string>('hex input data')}
value={
isHexData
? t<string>('Yes')
: t<string>('No')
}
/>
</div>
<div className='ui--row'>
<Output
className='full'
help={t<string>('The blake2b 256-bit hash of the actual input data.')}
isHidden={hash.length === 0}
isMonospace
label={t<string>('the resulting hash is')}
value={hash}
withCopy
/>
</div>
</div>
);
}
Example #22
Source File: test-precompile-xcm-transactor.ts From moonbeam with GNU General Public License v3.0 | 5 votes |
async function mockAssetBalance(context, assetBalance, assetDetails, sudoAccount, assetId) {
// Register the asset
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.assetManager.registerForeignAsset(
sourceLocationRelayAssetType,
relayAssetMetadata,
new BN(1),
true
)
)
.signAndSend(sudoAccount);
await context.createBlock();
let assets = (
(await context.polkadotApi.query.assetManager.assetIdType(assetId)) as any
).toJSON();
// make sure we created it
expect(assets["xcm"]["parents"]).to.equal(1);
// Get keys to modify balance
let module = xxhashAsU8a(new TextEncoder().encode("Assets"), 128);
let account_key = xxhashAsU8a(new TextEncoder().encode("Account"), 128);
let blake2concatAssetId = new Uint8Array([
...blake2AsU8a(assetId.toU8a(), 128),
...assetId.toU8a(),
]);
let blake2concatAccount = new Uint8Array([
...blake2AsU8a(hexToU8a(ALITH), 128),
...hexToU8a(ALITH),
]);
let overallAccountKey = new Uint8Array([
...module,
...account_key,
...blake2concatAssetId,
...blake2concatAccount,
]);
// Get keys to modify total supply
let assetKey = xxhashAsU8a(new TextEncoder().encode("Asset"), 128);
let overallAssetKey = new Uint8Array([...module, ...assetKey, ...blake2concatAssetId]);
await context.polkadotApi.tx.sudo
.sudo(
context.polkadotApi.tx.system.setStorage([
[u8aToHex(overallAccountKey), u8aToHex(assetBalance.toU8a())],
[u8aToHex(overallAssetKey), u8aToHex(assetDetails.toU8a())],
])
)
.signAndSend(sudoAccount);
await context.createBlock();
return;
}
Example #23
Source File: Create.tsx From crust-apps with Apache License 2.0 | 4 votes |
function Create ({ onClose, onStatusChange }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api, isEthereum } = useApi();
const [{ isNameValid, name }, setName] = useState<NameState>({ isNameValid: false, name: '' });
const [{ address, addressInput, isAddressExisting, isAddressValid }, setAddress] = useState<AddrState>({ address: '', addressInput: '', isAddressExisting: false, isAddressValid: false, isPublicKey: false });
const info = useCall<DeriveAccountInfo>(!!address && isAddressValid && api.derive.accounts.info, [address]);
const isValid = (isAddressValid && isNameValid) && !!info?.accountId;
const _onChangeAddress = useCallback(
(addressInput: string): void => {
let address = '';
let isAddressValid = true;
let isAddressExisting = false;
let isPublicKey = false;
try {
if (isEthereum) {
const rawAddress = hexToU8a(addressInput);
address = ethereumEncode(rawAddress);
isPublicKey = rawAddress.length === 20;
} else {
const publicKey = keyring.decodeAddress(addressInput);
address = keyring.encodeAddress(publicKey);
isPublicKey = publicKey.length === 32;
}
if (!isAddressValid) {
const old = keyring.getAddress(address);
if (old) {
const newName = old.meta.name || name;
isAddressExisting = true;
isAddressValid = true;
setName({ isNameValid: !!(newName || '').trim(), name: newName });
}
}
} catch (error) {
isAddressValid = false;
}
setAddress({ address: isAddressValid ? address : '', addressInput, isAddressExisting, isAddressValid, isPublicKey });
},
[isEthereum, name]
);
const _onChangeName = useCallback(
(name: string) => setName({ isNameValid: !!name.trim(), name }),
[]
);
const _onCommit = useCallback(
(): void => {
const status = { action: 'create' } as ActionStatus;
if (!isValid || !info?.accountId) {
return;
}
try {
const address = info.accountId.toString();
keyring.saveAddress(address, { genesisHash: keyring.genesisHash, name: name.trim(), tags: [] });
status.account = address;
status.status = address ? 'success' : 'error';
status.message = isAddressExisting
? t<string>('address edited')
: t<string>('address created');
InputAddress.setLastValue('address', address);
} catch (error) {
status.status = 'error';
status.message = (error as Error).message;
}
onStatusChange(status);
onClose();
},
[info, isAddressExisting, isValid, name, onClose, onStatusChange, t]
);
return (
<Modal header={t<string>('Add an address')}>
<Modal.Content>
<AddressRow
defaultName={name}
noDefaultNameOpacity
value={
isAddressValid
? info?.accountId?.toString()
: undefined
}
>
<Input
autoFocus
className='full'
help={t<string>('Paste here the address of the contact you want to add to your address book.')}
isError={!isAddressValid}
label={t<string>('address')}
onChange={_onChangeAddress}
onEnter={_onCommit}
placeholder={t<string>('new address')}
value={addressInput}
/>
<Input
className='full'
help={t<string>('Type the name of your contact. This name will be used across all the apps. It can be edited later on.')}
isError={!isNameValid}
label={t<string>('name')}
onChange={_onChangeName}
onEnter={_onCommit}
value={name}
/>
</AddressRow>
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<Button
icon='save'
isDisabled={!isValid}
label={t<string>('Save')}
onClick={_onCommit}
/>
</Modal.Actions>
</Modal>
);
}
Example #24
Source File: QrSigner.ts From sdk with Apache License 2.0 | 4 votes |
async function _constructDataFromBytes(bytes: Uint8Array, multipartComplete = false) {
const frameInfo = hexStripPrefix(u8aToHex(bytes.slice(0, 5)));
const frameCount = parseInt(frameInfo.substr(2, 4), 16);
const isMultipart = frameCount > 1; // for simplicity, even single frame payloads are marked as multipart.
const currentFrame = parseInt(frameInfo.substr(6, 4), 16);
const uosAfterFrames = hexStripPrefix(u8aToHex(bytes.slice(5)));
// UOS after frames can be metadata json
if (isMultipart && !multipartComplete) {
const partData = {
currentFrame,
frameCount,
isMultipart,
partData: uosAfterFrames,
};
return partData;
}
const zerothByte = uosAfterFrames.substr(0, 2);
const firstByte = uosAfterFrames.substr(2, 2);
const secondByte = uosAfterFrames.substr(4, 2);
let action: string;
try {
// decode payload appropriately via UOS
switch (zerothByte) {
case "45": {
// Ethereum UOS payload
const data = {
data: {}, // for consistency with legacy data format.
};
action = firstByte === "00" || firstByte === "01" ? "signData" : firstByte === "01" ? "signTransaction" : null;
const address = uosAfterFrames.substr(4, 44);
data["action"] = action;
data.data["account"] = address;
if (action === "signData") {
data.data["rlp"] = uosAfterFrames[13];
} else if (action === "signTransaction") {
data.data["data"] = uosAfterFrames[13];
} else {
throw new Error("Could not determine action type.");
}
return data;
}
case "53": {
// Substrate UOS payload
const data = {
data: {}, // for consistency with legacy data format.
};
try {
data.data["crypto"] = firstByte === "00" ? "ed25519" : firstByte === "01" ? "sr25519" : null;
const pubKeyHex = uosAfterFrames.substr(6, 64);
const publicKeyAsBytes = hexToU8a("0x" + pubKeyHex);
const hexEncodedData = "0x" + uosAfterFrames.slice(70);
const hexPayload = hexEncodedData.slice(0, -64);
const genesisHash = `0x${hexEncodedData.substr(-64)}`;
const rawPayload = hexToU8a(hexPayload);
data.data["genesisHash"] = genesisHash;
const isOversized = rawPayload.length > 256;
const network = SUBSTRATE_NETWORK_LIST[genesisHash];
// if (!network) {
// throw new Error(`Signer does not currently support a chain with genesis hash: ${genesisHash}`);
// }
switch (secondByte) {
case "00": // sign mortal extrinsic
case "02": // sign immortal extrinsic
data["action"] = isOversized ? "signData" : "signTransaction";
data["oversized"] = isOversized;
data["isHash"] = isOversized;
const [offset] = compactFromU8a(rawPayload);
const payload = rawPayload.subarray(offset);
// data.data.data = isOversized
// ? await blake2b(u8aToHex(payload, -1, false))
// : rawPayload;
data.data["data"] = rawPayload; // ignore oversized data for now
data.data["account"] = encodeAddress(publicKeyAsBytes, network?.prefix || 0); // encode to the prefix;
break;
case "01": // data is a hash
data["action"] = "signData";
data["oversized"] = false;
data["isHash"] = true;
data.data["data"] = hexPayload;
data.data["account"] = encodeAddress(publicKeyAsBytes, network?.prefix || 0); // default to Kusama
break;
}
} catch (e) {
throw new Error("Error: something went wrong decoding the Substrate UOS payload: " + uosAfterFrames);
}
return data;
}
default:
throw new Error("Error: Payload is not formatted correctly: " + bytes);
}
} catch (e) {
throw new Error("we cannot handle the payload: " + bytes);
}
}
Example #25
Source File: index.tsx From crust-apps with Apache License 2.0 | 4 votes |
function Claims(): React.ReactElement<Props> { const [didCopy, setDidCopy] = useState(false); const [ethereumAddress, setEthereumAddress] = useState<string | undefined | null>(null); const [signature, setSignature] = useState<EcdsaSignature | null>(null); const [step, setStep] = useState<Step>(Step.Account); const [accountId, setAccountId] = useState<string | null>(null); const { api, systemChain } = useApi(); const { t } = useTranslation(); const [statusOpen, setStatusOpen] = useState<boolean>(false); const [result, setResult] = useState<string>(''); const [status, setStatus] = useState<string>(''); const [ethereumTxHashValid, setEthereumTxHashValid] = useState<boolean>(false); const [isBusy, setIsBusy] = useState<boolean>(false); const [isValid, setIsValid] = useState(false); const [ethereumTxHash, setEthereumTxHash] = useState<string | undefined | null>(null); // This preclaimEthereumAddress holds the result of `api.query.claims.preclaims`: // - an `EthereumAddress` when there's a preclaim // - null if no preclaim // - `PRECLAIMS_LOADING` if we're fetching the results const [preclaimEthereumAddress, setPreclaimEthereumAddress] = useState<string | null | undefined | typeof PRECLAIMS_LOADING>(PRECLAIMS_LOADING); const isPreclaimed = !!preclaimEthereumAddress && preclaimEthereumAddress !== PRECLAIMS_LOADING; const claimLimit = useCall<BalanceOf>(api.query.claims.claimLimit); // Everytime we change account, reset everything, and check if the accountId // has a preclaim. useEffect(() => { if (!accountId) { return; } setStep(Step.Account); setEthereumAddress(null); setEthereumTxHash(null); setPreclaimEthereumAddress(PRECLAIMS_LOADING); if (!api.query.claims || !api.query.claims.preclaims) { return setPreclaimEthereumAddress(null); } api.query.claims .preclaims<Option<EthereumAddress>>(accountId) .then((preclaim): void => { const address = preclaim.unwrapOr(null)?.toString(); setEthereumAddress(address); setPreclaimEthereumAddress(address); }) .catch((): void => setPreclaimEthereumAddress(null)); }, [accountId, api.query.claims, api.query.claims.preclaims]); // Old claim process used `api.tx.claims.claim`, and didn't have attest const isOldClaimProcess = !api.tx.claims.claimAttest; useEffect(() => { if (didCopy) { setTimeout((): void => { setDidCopy(false); }, 1000); } }, [didCopy]); const goToStepAccount = useCallback(() => { setStep(Step.Account); setEthereumTxHash(""); setEthereumTxHashValid(false); }, []); const goToStepSign = useCallback(() => { setStep(Step.Sign); }, []); const goToStepClaim = useCallback(() => { setStep(Step.Claim); }, []); const handleAccountStep = useCallback(async () => { setIsBusy(true); api.query.claims .claimed<Option<BalanceOf>>(ethereumTxHash?.toString()) .then(async (claim): Promise<void> => { const isClaimed = JSON.parse(JSON.stringify(claim)); if (isClaimed) { setResult('AlreadyClaimed'); setStatus('error'); setStatusOpen(true); } else { const result = await httpPost("https://claim.crust.network/claim/" + ethereumTxHash); setIsBusy(false); setResult(result.statusText); setStatus(result.status); if (result.code == 200) { setEthereumTxHashValid(true); goToStepSign(); } else { api.query.claims .claims<Option<BalanceOf>>(ethereumTxHash?.toString()) .then(async (claim): Promise<void> => { const claimOpt = JSON.parse(JSON.stringify(claim)); if (claimOpt) { setResult('MintClaimSuccess'); setStatus('success'); setEthereumTxHashValid(true); goToStepSign(); } else { setResult('MintError, Please try again'); setStatus('error'); } }) .catch((): void => setIsBusy(false)); } setStatusOpen(true); } }) .catch((): void => setIsBusy(false)) .finally(() => setIsBusy(false)); }, [ethereumAddress, goToStepClaim, goToStepSign, isPreclaimed, isOldClaimProcess, ethereumTxHash]); const onChangeEthereumTxHash = useCallback((hex: string) => { let [isValid, value] = convertInput(hex); isValid = isValid && ( length !== -1 ? value.length === 32 : value.length !== 0 ); setIsValid(isValid); setEthereumTxHash(hex.trim()); }, [ethereumTxHash]); function convertInput(value: string): [boolean, Uint8Array] { if (value === '0x') { return [true, new Uint8Array([])]; } else if (value.startsWith('0x')) { try { return [true, hexToU8a(value)]; } catch (error) { return [false, new Uint8Array([])]; } } // maybe it is an ss58? try { return [true, decodeAddress(value)]; } catch (error) { // we continue } return isAscii(value) ? [true, stringToU8a(value)] : [value === '0x', new Uint8Array([])]; } // Depending on the account, decide which step to show. // const handleAccountStep = useCallback(() => { // if (isPreclaimed) { // goToStepClaim(); // } else if (ethereumAddress || isOldClaimProcess) { // goToStepSign(); // } else { // setStep(Step.ETHAddress); // } // }, [ethereumAddress, goToStepClaim, goToStepSign, isPreclaimed, isOldClaimProcess]); const onChangeSignature = useCallback((event: React.SyntheticEvent<Element>) => { const { value: signatureJson } = event.target as HTMLInputElement; const { ethereumAddress, signature } = recoverFromJSON(signatureJson); setEthereumAddress(ethereumAddress?.toString()); setSignature(signature); }, []); const onChangeEthereumAddress = useCallback((value: string) => { // FIXME We surely need a better check than just a trim setEthereumAddress(value.trim()); }, []); const onCopy = useCallback(() => { setDidCopy(true); }, []); // If it's 1/ not preclaimed and 2/ not the old claiming process, fetch the // statement kind to sign. const statementKind = useCall<StatementKind | null>(!isPreclaimed && !isOldClaimProcess && !!ethereumAddress && api.query.claims.signing, [ethereumAddress], transformStatement); const statementSentence = getStatement(systemChain, statementKind)?.sentence || ''; const prefix = u8aToString(api.consts.claims.prefix.toU8a(true)); const payload = accountId ? `${prefix}${u8aToHex(decodeAddress(accountId), -1, false)}${statementSentence}${ethereumTxHash?.substring(2)}` : ''; return ( <main> {!isOldClaimProcess && <Warning />} <h2> {t<string>('Claim your {{token}} tokens', { replace: { token: TokenUnit.abbr } })} </h2> <Columar> <Columar.Column> <Card withBottomMargin> <h3>{t<string>('0. Burn your ')}<a href='https://etherscan.io/token/0x32a7C02e79c4ea1008dD6564b35F131428673c41'>{t('ERC20 CRU')}</a>{t<string>(', transfer to address ')} <a href='https://etherscan.io/address/0x0000000000000000000000000000000000000001' target="_blank">0x0000000000000000000000000000000000000001</a></h3> <Banner type='warning'> <p>{t<string>('Please make sure you have the authority to make signature with the private key of the wallet account, using an exchange account to sent a transfer (withdrawal) transaction will be invalidated and cause asset loss, you are responsible for the consequences')}</p> </Banner> <img style={{'marginLeft': 'auto', 'marginRight': 'auto', 'display': 'block', "width": "150px" }} src={burnPng as string} /> </Card> {(<Card withBottomMargin> <h3>{t<string>(`1. Select your {{chain}} account and enter`, { replace: { chain: systemChain } })} <a href='https://etherscan.io/token/0x32a7C02e79c4ea1008dD6564b35F131428673c41'>{t('ERC20 CRU')}</a> {t<string>(' transfer tx hash')}<span> {t<string>(`, If your claim amount is greater than the claim limit `)} <span style={{ 'color': '#ff8812', 'textDecoration': 'underline', 'fontStyle': 'italic' }}>({formatBalance(claimLimit, { withUnit: 'CRU' })})</span> {t<string>(', please wait for the limit update')} </span> </h3> <InputAddress defaultValue={accountId} help={t<string>('The account you want to claim to.')} isDisabled={ethereumTxHashValid} label={t<string>('claim to account')} onChange={setAccountId} type='account' /> <Input autoFocus className='full' help={t<string>('The Ethereum CRU transfer tx hash (starting by "0x")')} isDisabled={ethereumTxHashValid} isError={!isValid} label={t<string>('Ethereum tx hash')} onChange={onChangeEthereumTxHash} placeholder={t<string>('0x prefixed hex, e.g. 0x1234 or ascii data')} value={ethereumTxHash || ''} /> {(step === Step.Account) && (<Button.Group> <Button icon='sign-in-alt' isBusy={isBusy} isDisabled={preclaimEthereumAddress === PRECLAIMS_LOADING || ethereumTxHash === null || ethereumTxHash === '' || !isValid} label={preclaimEthereumAddress === PRECLAIMS_LOADING ? t<string>('Loading') : t<string>('Continue') } onClick={handleAccountStep} /> </Button.Group>)} <HttpStatus isStatusOpen={statusOpen} message={result} setStatusOpen={setStatusOpen} status={status} /> </Card>)} { // We need to know the ethereuem address only for the new process // to be able to know the statement kind so that the users can sign it (step >= Step.ETHAddress && !isPreclaimed && !isOldClaimProcess) && ( <Card withBottomMargin> <h3>{t<string>('2. Enter the ETH address from the sale.')}</h3> <Input autoFocus className='full' help={t<string>('The the Ethereum address you burnt your ERC20 CRU in step 0 (starting by "0x")')} label={t<string>('Pre-sale ethereum address')} onChange={onChangeEthereumAddress} value={ethereumAddress || ''} /> {(step === Step.ETHAddress) && ( <Button.Group> <Button icon='sign-in-alt' isDisabled={!ethereumAddress} label={t<string>('Continue')} onClick={goToStepSign} /> </Button.Group> )} </Card> )} {(step >= Step.Sign && !isPreclaimed) && ( <Card> <h3>{t<string>('{{step}}. Sign with your ETH address', { replace: { step: isOldClaimProcess ? '2' : '3' } })}</h3> {!isOldClaimProcess && ( <Statement kind={statementKind} systemChain={systemChain} /> )} <div>{t<string>('Copy the following string and sign it with the Ethereum account you burnt your ERC20 CRU in step 0, using the string as the payload, and then paste the transaction signature object below:')}</div> <CopyToClipboard onCopy={onCopy} text={payload} > <Payload data-for='tx-payload' data-tip > {payload} </Payload> </CopyToClipboard> <Tooltip place='right' text={didCopy ? t<string>('copied') : t<string>('click to copy')} trigger='tx-payload' /> <div>{t<string>('Paste the signed message into the field below. The placeholder text is there as a hint to what the message should look like:')}</div> <Signature onChange={onChangeSignature} placeholder={`{\n "address": "0x ...",\n "msg": "0x ...",\n "sig": "...",\n "version": "3",\n "signer": "..."\n}`} rows={10} /> {(step === Step.Sign) && ( <Button.Group> <Button icon='sign-in-alt' isDisabled={!accountId || !signature} label={t<string>('Confirm claim')} onClick={goToStepClaim} /> </Button.Group> )} </Card> )} </Columar.Column> <Columar.Column> {(step >= Step.Claim) && ( isPreclaimed ? <AttestDisplay accountId={accountId} ethereumAddress={ethereumAddress} onSuccess={goToStepAccount} statementKind={statementKind} systemChain={systemChain} /> : <ClaimDisplay accountId={accountId} ethereumAddress={ethereumAddress} ethereumSignature={signature} isOldClaimProcess={isOldClaimProcess} onSuccess={goToStepAccount} statementKind={statementKind} ethereumTxHash={ethereumTxHash} /> )} </Columar.Column> </Columar> </main> ); }
Example #26
Source File: test-xcm-para.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeParachain(
"XCM - send_para_a_asset_from_para_b_to_para_c",
{ chain: "moonbase-local", numberOfParachains: 3 },
(context) => {
let keyring: Keyring,
alith: KeyringPair,
baltathar: KeyringPair,
parachainOne: ApiPromise,
parachainTwo: ApiPromise,
parachainThree: ApiPromise,
relayOne: ApiPromise,
assetId: string,
sourceLocationParaA: SourceLocation,
initialBalance: number;
before("First send relay chain asset to parachain", async function () {
keyring = new Keyring({ type: "ethereum" });
// Setup Relaychain
relayOne = context._polkadotApiRelaychains[0];
// Setup Parachains
alith = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
baltathar = await keyring.addFromUri(BALTATHAR_PRIV_KEY, null, "ethereum");
parachainOne = context.polkadotApiParaone;
parachainTwo = context._polkadotApiParachains[1].apis[0];
parachainThree = context._polkadotApiParachains[2].apis[0];
// Log events
logEvents(parachainOne, "PARA A");
logEvents(parachainTwo, "PARA B");
logEvents(parachainThree, "PARA C");
logEvents(relayOne, "RELAY");
initialBalance = Number(
((await parachainOne.query.system.account(BALTATHAR)) as any).data.free
);
// Get Pallet balances index
const metadata = await parachainOne.rpc.state.getMetadata();
const palletIndex = (metadata.asLatest.toHuman().pallets as Array<any>).find((pallet) => {
return pallet.name === "Balances";
}).index;
expect(palletIndex);
sourceLocationParaA = {
XCM: {
parents: new BN(1),
interior: { X2: [{ Parachain: new BN(1000) }, { Palletinstance: new BN(palletIndex) }] },
},
};
// PARACHAIN B
// registerAsset
({ assetId } = await registerAssetToParachain(
parachainTwo,
alith,
sourceLocationParaA,
paraAssetMetadata
));
// PARACHAIN C
// registerAsset
await registerAssetToParachain(parachainThree, alith, sourceLocationParaA, paraAssetMetadata);
});
it("should be able to receive an asset back in para a from para b", async function () {
// PARACHAIN A
// transfer 100 units to parachain B
await createBlockWithExtrinsicParachain(
parachainOne,
baltathar,
parachainOne.tx.xTokens.transfer(
"SelfReserve",
HUNDRED_UNITS_PARA,
{
V1: {
parents: new BN(1),
interior: {
X2: [
{ Parachain: new BN(2000) },
{ AccountKey20: { network: "Any", key: hexToU8a(BALTATHAR) } },
],
},
},
},
new BN(4000000000)
)
);
await waitOneBlock(parachainTwo, 6);
// PARACHAIN B
// transfer 100 units to parachain C
const { events: eventsTransfer2 } = await createBlockWithExtrinsicParachain(
parachainTwo,
baltathar,
parachainTwo.tx.xTokens.transfer(
{ OtherReserve: assetId },
HUNDRED_UNITS_PARA,
{
V1: {
parents: new BN(1),
interior: {
X2: [
{ Parachain: new BN(3000) },
{ AccountKey20: { network: "Any", key: hexToU8a(BALTATHAR) } },
],
},
},
},
new BN(4000000000)
)
);
expect(eventsTransfer2[2].toHuman().method).to.eq("XcmpMessageSent");
expect(eventsTransfer2[3].toHuman().method).to.eq("Transferred");
expect(eventsTransfer2[8].toHuman().method).to.eq("ExtrinsicSuccess");
await waitOneBlock(parachainThree, 3);
// Verify that difference is 100 units plus fees (less than 1% of 10^18)
const targetBalance: number = Number(BigInt(BigInt(initialBalance) - HUNDRED_UNITS_PARA));
let expectedBaltatharParaTwoBalance = BigInt(0);
let paraAXcmFee = BigInt(400000000);
const diff =
Number(((await parachainOne.query.system.account(BALTATHAR)) as any).data.free) -
targetBalance;
expect(diff < 10000000000000000).to.eq(true);
expect(
((await parachainTwo.query.assets.account(assetId, BALTATHAR)) as any).balance.toString()
).to.eq(expectedBaltatharParaTwoBalance.toString());
expect(
((await parachainThree.query.assets.account(assetId, BALTATHAR)) as any).balance.toString()
).to.eq((BigInt(HUNDRED_UNITS_PARA) - paraAXcmFee).toString());
});
}
);
Example #27
Source File: getBlock.test.ts From metamask-snap-polkadot with Apache License 2.0 | 4 votes |
describe('Test rpc handler function: getBlock', function() {
const walletStub = new WalletMock();
afterEach(function() {
walletStub.reset();
});
it('should return block on block id as number', async function () {
// api stub
const apiStub = {rpc: {chain: {getBlock: sinon.stub(), getBlockHash: sinon.stub()}}};
apiStub.rpc.chain.getBlockHash.returns(
hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as BlockHash
);
// eslint-disable-next-line max-len
apiStub.rpc.chain.getBlock.returns({block:{hash: {toHex: (): string => "0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75"}, header: {number: 10}}});
const api = apiStub as unknown as ApiPromise;
const result = await getBlock(1, api);
expect(result).not.to.be.null;
expect(result.hash).to.be.eq("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75");
expect(result.number).to.be.eq("10");
expect(apiStub.rpc.chain.getBlockHash).to.have.been.calledOnceWith(1);
// eslint-disable-next-line max-len
expect(apiStub.rpc.chain.getBlock).to.have.been.calledOnceWith(hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as BlockHash);
});
it('should return block on block id as string', async function () {
// api stub
const apiStub = {rpc: {chain: {getBlock: sinon.stub(), getBlockHash: sinon.stub()}}};
apiStub.rpc.chain.getBlockHash.returns(
hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as BlockHash
);
// eslint-disable-next-line max-len
apiStub.rpc.chain.getBlock.returns({block:{hash: {toHex: (): string => "0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75"}, header: {number: 10}}});
const api = apiStub as unknown as ApiPromise;
const result = await getBlock("1", api);
expect(result).not.to.be.null;
expect(result.hash).to.be.eq("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75");
expect(result.number).to.be.eq("10");
expect(apiStub.rpc.chain.getBlockHash).to.have.been.calledOnceWith(1);
// eslint-disable-next-line max-len
expect(apiStub.rpc.chain.getBlock).to.have.been.calledOnceWith(hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as BlockHash);
});
it('should return block on block hash as string', async function () {
// api stub
const apiStub = {rpc: {chain: {getBlock: sinon.stub()}}};
apiStub.rpc.chain.getBlock.returns({});
// eslint-disable-next-line max-len
apiStub.rpc.chain.getBlock.returns({block:{hash: {toHex: (): string => "0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75"}, header: {number: 10}}});
const api = apiStub as unknown as ApiPromise;
// eslint-disable-next-line max-len
const result = await getBlock("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75", api);
expect(result).not.to.be.null;
expect(result.hash).to.be.eq("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75");
expect(result.number).to.be.eq("10");
// eslint-disable-next-line max-len
expect(apiStub.rpc.chain.getBlock).to.have.been.calledOnceWith("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75");
});
it('should return latest block on "latest" as parameter', async function () {
// api stub
const apiStub = {rpc: {chain: {getBlock: sinon.stub(), getHeader: sinon.stub()}}};
apiStub.rpc.chain.getBlock.returns({});
// eslint-disable-next-line max-len
apiStub.rpc.chain.getBlock.returns({block:{hash: {toHex: (): string => "0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75"}, header: {number: 10}}});
// eslint-disable-next-line max-len
apiStub.rpc.chain.getHeader.returns({hash: hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as H256});
const api = apiStub as unknown as ApiPromise;
const result = await getBlock("latest", api);
expect(result).not.to.be.null;
expect(result.hash).to.be.eq("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75");
expect(result.number).to.be.eq("10");
expect(apiStub.rpc.chain.getHeader).to.have.been.calledOnce;
// eslint-disable-next-line max-len
expect(apiStub.rpc.chain.getBlock).to.have.been.calledOnceWith(hexToU8a("0xc9fb400866641ca80ef3e760d904fe15a8c9eda6ff1bd769b0628e26e82d5c75") as BlockHash);
});
it('should return null on invalid string as parameter', async function () {
const api = {} as unknown as ApiPromise;
const result = await getBlock("zz", api);
expect(result).to.be.null;
});
it('should return null on empty parameters object', async function () {
const api = {} as unknown as ApiPromise;
const result = await getBlock(null, api);
expect(result).to.be.null;
});
});
Example #28
Source File: index.tsx From crust-apps with Apache License 2.0 | 4 votes |
function CSMClaims (): React.ReactElement<Props> { const [didCopy, setDidCopy] = useState(false); const [ethereumAddress, setEthereumAddress] = useState<string | undefined | null>(null); const [signature, setSignature] = useState<EcdsaSignature | null>(null); const [step, setStep] = useState<Step>(Step.Account); const [accountId, setAccountId] = useState<string | null>(null); const { api, systemChain } = useApi(); const { t } = useTranslation(); const [statusOpen, setStatusOpen] = useState<boolean>(false); const [result, setResult] = useState<string>(''); const [status, setStatus] = useState<string>(''); const [ethereumTxHashValid, setEthereumTxHashValid] = useState<boolean>(false); const [isBusy, setIsBusy] = useState<boolean>(false); const [isValid, setIsValid] = useState(false); const [ethereumTxHash, setEthereumTxHash] = useState<string | undefined | null>(null); const csmClaimLimit = useCall<BalanceOf>(api.query.claims.csmClaimLimit); // This preclaimEthereumAddress holds the result of `api.query.claims.preclaims`: // - an `EthereumAddress` when there's a preclaim // - null if no preclaim // - `PRECLAIMS_LOADING` if we're fetching the results const [preclaimEthereumAddress, setPreclaimEthereumAddress] = useState<string | null | undefined | typeof PRECLAIMS_LOADING>(PRECLAIMS_LOADING); const isPreclaimed = !!preclaimEthereumAddress && preclaimEthereumAddress !== PRECLAIMS_LOADING; // Everytime we change account, reset everything, and check if the accountId // has a preclaim. useEffect(() => { if (!accountId) { return; } setStep(Step.Account); setEthereumAddress(null); setEthereumTxHash(null); setPreclaimEthereumAddress(PRECLAIMS_LOADING); if (!api.query.claims || !api.query.claims.preclaims) { return setPreclaimEthereumAddress(null); } api.query.claims .preclaims<Option<EthereumAddress>>(accountId) .then((preclaim): void => { const address = preclaim.unwrapOr(null)?.toString(); setEthereumAddress(address); setPreclaimEthereumAddress(address); }) .catch((): void => setPreclaimEthereumAddress(null)); }, [accountId, api.query.claims, api.query.claims.preclaims]); // Old claim process used `api.tx.claims.claim`, and didn't have attest const isOldClaimProcess = !api.tx.claims.claimAttest; useEffect(() => { if (didCopy) { setTimeout((): void => { setDidCopy(false); }, 1000); } }, [didCopy]); const goToStepAccount = useCallback(() => { setStep(Step.Account); setEthereumTxHash(""); setEthereumTxHashValid(false); }, []); const goToStepSign = useCallback(() => { setStep(Step.Sign); }, []); const goToStepClaim = useCallback(() => { setStep(Step.Claim); }, []); const handleAccountStep = useCallback(async () => { setIsBusy(true); const result = await httpPost("https://csm-bridge-api.crust.network/csmClaim/" + ethereumTxHash); setIsBusy(false); setResult(result.statusText); setStatus(result.status); if (result.code == 200) { setStatusOpen(true); setEthereumTxHashValid(true); goToStepSign(); } else { api.query.claims .csmClaims<Option<BalanceOf>>(ethereumTxHash?.toString()) .then((claim): void => { const claimOpt = JSON.parse(JSON.stringify(claim)); if (claimOpt) { api.query.claims .csmClaimed<Option<BalanceOf>>(ethereumTxHash?.toString()) .then((claimed): void => { const isClaimed = JSON.parse(JSON.stringify(claimed)); if (isClaimed) { setStatusOpen(true); } else { setStatusOpen(true); setResult('MintClaimSuccess'); setStatus('success'); setEthereumTxHashValid(true); goToStepSign(); } }); } else { setStatusOpen(true); } }) .catch((): void => setIsBusy(false)); } }, [ethereumAddress, goToStepAccount, goToStepClaim, goToStepSign, isPreclaimed, isOldClaimProcess, ethereumTxHash]); const onChangeEthereumTxHash = useCallback((hex: string) => { let [isValid, value] = convertInput(hex); isValid = isValid && ( length !== -1 ? value.length === 32 : value.length !== 0 ); setIsValid(isValid); setEthereumTxHash(hex.trim()); }, [ethereumTxHash]); function convertInput (value: string): [boolean, Uint8Array] { if (value === '0x') { return [true, new Uint8Array([])]; } else if (value.startsWith('0x')) { try { return [true, hexToU8a(value)]; } catch (error) { return [false, new Uint8Array([])]; } } // maybe it is an ss58? try { return [true, decodeAddress(value)]; } catch (error) { // we continue } return isAscii(value) ? [true, stringToU8a(value)] : [value === '0x', new Uint8Array([])]; } // Depending on the account, decide which step to show. // const handleAccountStep = useCallback(() => { // if (isPreclaimed) { // goToStepClaim(); // } else if (ethereumAddress || isOldClaimProcess) { // goToStepSign(); // } else { // setStep(Step.ETHAddress); // } // }, [ethereumAddress, goToStepClaim, goToStepSign, isPreclaimed, isOldClaimProcess]); const onChangeSignature = useCallback((event: React.SyntheticEvent<Element>) => { const { value: signatureJson } = event.target as HTMLInputElement; const { ethereumAddress, signature } = recoverFromJSON(signatureJson); setEthereumAddress(ethereumAddress?.toString()); setSignature(signature); }, []); const onChangeEthereumAddress = useCallback((value: string) => { // FIXME We surely need a better check than just a trim setEthereumAddress(value.trim()); }, []); const onCopy = useCallback(() => { setDidCopy(true); }, []); // If it's 1/ not preclaimed and 2/ not the old claiming process, fetch the // statement kind to sign. const statementKind = useCall<StatementKind | null>(!isPreclaimed && !isOldClaimProcess && !!ethereumAddress && api.query.claims.signing, [ethereumAddress], transformStatement); const statementSentence = getStatement(systemChain, statementKind)?.sentence || ''; // const prefix = u8aToString(api.consts.claims.CsmPrefix.toU8a(true)); const prefix = 'Pay CSMs to the Crust account:' const payload = accountId ? `${prefix}${u8aToHex(decodeAddress(accountId), -1, false)}${statementSentence}${ethereumTxHash?.substring(2)}` : ''; return ( <main> {!isOldClaimProcess && <Warning />} <h1> <Trans>Claim your <em>CSM</em> tokens</Trans> </h1> <Columar> <Columar.Column> <Card withBottomMargin> <h3><span style={{"wordWrap": "break-word", "wordBreak": "break-all"}}>{t<string>(`0. Please make sure you have the authority to make signature with the private key of the wallet account `)}<span style={{ 'fontWeight': 'bold' }}>({t<string>('address: ')}<a href='https://etherscan.io/address/0x17a9037cdfb24ffcc13697d03c3bcd4dff34732b' target="_blank">0x17A9037cdFB24FfcC13697d03C3bcd4DFF34732b</a>)</span><span>{t<string>(', using an exchange account to sent a transfer (withdrawal) transaction will be invalidated and cause asset loss.')}</span> <span style={{ 'fontWeight': 'bold', 'color': 'red' }}>{t<string>(` You are responsible for the consequences!`)}</span></span></h3> <img style={{'marginLeft': 'auto', 'marginRight': 'auto', 'display': 'block', "width": "150px" }} src={claimPng as string} /> </Card> {(<Card withBottomMargin> <h3>{t<string>(`1. Select your {{chain}} account and enter`, { replace: { chain: systemChain } })} <a href='https://rinkeby.etherscan.io/token/0x7a1c61c526dae21c23b50a490c18d04f8077608f'>{t('ERC20 CSM')}</a> {t<string>('transfer tx hash')}, <span>{t<string>(`The remaining claim limit is `)}<span style={{'color': '#ff8812', 'textDecoration': 'underline', 'fontStyle': 'italic'}}>{formatBalance(csmClaimLimit, { decimals: 12, withUnit: 'CSM' })}</span><span>{t<string>(`, If your claim amount is greater than the claim limit, please wait for the limit update`)}</span></span> </h3> <InputAddress defaultValue={accountId} help={t<string>('The account you want to claim to.')} isDisabled={ethereumTxHashValid} label={t<string>('claim to account')} onChange={setAccountId} type='account' /> <Input autoFocus className='full' help={t<string>('The Ethereum CSM transfer tx hash (starting by "0x")')} isDisabled={ethereumTxHashValid} isError={!isValid} label={t<string>('Ethereum tx hash')} onChange={onChangeEthereumTxHash} placeholder={t<string>('0x prefixed hex, e.g. 0x1234 or ascii data')} value={ethereumTxHash || ''} /> {(step === Step.Account) && (<Button.Group> <Button icon='sign-in-alt' isBusy={isBusy} isDisabled={preclaimEthereumAddress === PRECLAIMS_LOADING || ethereumTxHash === null || ethereumTxHash === '' || !isValid} label={preclaimEthereumAddress === PRECLAIMS_LOADING ? t<string>('Loading') : t<string>('Continue') } onClick={handleAccountStep} /> </Button.Group>)} <HttpStatus isStatusOpen={statusOpen} message={result} setStatusOpen={setStatusOpen} status={status} /> </Card>)} { // We need to know the ethereuem address only for the new process // to be able to know the statement kind so that the users can sign it (step >= Step.ETHAddress && !isPreclaimed && !isOldClaimProcess) && ( <Card withBottomMargin> <h3>{t<string>('2. Enter the ETH address from the sale.')}</h3> <Input autoFocus className='full' help={t<string>('The the Ethereum address you used during the pre-sale (starting by "0x")')} label={t<string>('Pre-sale ethereum address')} onChange={onChangeEthereumAddress} value={ethereumAddress || ''} /> {(step === Step.ETHAddress) && ( <Button.Group> <Button icon='sign-in-alt' isDisabled={!ethereumAddress} label={t<string>('Continue')} onClick={goToStepSign} /> </Button.Group> )} </Card> )} {(step >= Step.Sign && !isPreclaimed) && ( <Card> <h3>{t<string>('{{step}}. Sign with your ETH address', { replace: { step: isOldClaimProcess ? '2' : '3' } })}</h3> {!isOldClaimProcess && ( <Statement kind={statementKind} systemChain={systemChain} /> )} <div>{t<string>('Copy the following string and sign it with the Ethereum account you used during the pre-sale in the wallet of your choice, using the string as the payload, and then paste the transaction signature object below:')}</div> <CopyToClipboard onCopy={onCopy} text={payload} > <Payload data-for='tx-payload' data-tip > {payload} </Payload> </CopyToClipboard> <Tooltip place='right' text={didCopy ? t<string>('copied') : t<string>('click to copy')} trigger='tx-payload' /> <div>{t<string>('Paste the signed message into the field below. The placeholder text is there as a hint to what the message should look like:')}</div> <Signature onChange={onChangeSignature} placeholder={`{\n "address": "0x ...",\n "msg": "${prefix}...",\n "sig": "0x ...",\n "version": "3",\n "signer": "..."\n}`} rows={10} /> {(step === Step.Sign) && ( <Button.Group> <Button icon='sign-in-alt' isDisabled={!accountId || !signature} label={t<string>('Confirm claim')} onClick={goToStepClaim} /> </Button.Group> )} </Card> )} </Columar.Column> <Columar.Column> {(step >= Step.Claim) && ( isPreclaimed ? <AttestDisplay accountId={accountId} ethereumAddress={ethereumAddress} onSuccess={goToStepAccount} statementKind={statementKind} systemChain={systemChain} /> : <ClaimDisplay accountId={accountId} ethereumAddress={ethereumAddress} ethereumSignature={signature} isOldClaimProcess={isOldClaimProcess} onSuccess={goToStepAccount} statementKind={statementKind} ethereumTxHash={ethereumTxHash} /> )} </Columar.Column> </Columar> </main> ); }
Example #29
Source File: test-precompile-local-assets-erc20.ts From moonbeam with GNU General Public License v3.0 | 4 votes |
describeDevMoonbeamAllEthTxTypes(
"Precompiles - Assets-ERC20 Wasm",
(context) => {
let sudoAccount, baltatharAccount, assetId, iFace, assetAddress, contractInstanceAddress;
before("Setup contract and mock balance", async () => {
const keyring = new Keyring({ type: "ethereum" });
sudoAccount = await keyring.addFromUri(ALITH_PRIV_KEY, null, "ethereum");
baltatharAccount = await keyring.addFromUri(BALTATHAR_PRIV_KEY, null, "ethereum");
// registerAsset
const { events: eventsRegister } = await createBlockWithExtrinsic(
context,
sudoAccount,
context.polkadotApi.tx.sudo.sudo(
context.polkadotApi.tx.assetManager.registerLocalAsset(
baltatharAccount.address,
baltatharAccount.address,
true,
new BN(1)
)
)
);
// Look for assetId in events
eventsRegister.forEach((e) => {
if (e.section.toString() === "assetManager") {
assetId = e.data[0].toHex();
}
});
assetId = assetId.replace(/,/g, "");
// Set metadata
await createBlockWithExtrinsic(
context,
baltatharAccount,
context.polkadotApi.tx.localAssets.setMetadata(assetId, "Local", "Local", new BN(12))
);
// mint asset
await createBlockWithExtrinsic(
context,
baltatharAccount,
context.polkadotApi.tx.localAssets.mint(assetId, baltatharAccount.address, 100000000000000)
);
assetAddress = u8aToHex(new Uint8Array([...hexToU8a("0xFFFFFFFE"), ...hexToU8a(assetId)]));
const contractData = await getCompiled("LocalAssetExtendedErc20Instance");
iFace = new ethers.utils.Interface(contractData.contract.abi);
const { contract, rawTx } = await createContract(context, "LocalAssetExtendedErc20Instance");
contractInstanceAddress = contract.options.address;
await context.createBlock({ transactions: [rawTx] });
});
it("allows to call name", async function () {
let data = iFace.encodeFunctionData(
// action
"name",
[]
);
const tx_call = await customWeb3Request(context.web3, "eth_call", [
{
from: ALITH,
value: "0x0",
gas: "0x10000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
},
]);
let expected = stringToHex("Local");
let offset = numberToHex(32).slice(2).padStart(64, "0");
let length = numberToHex(5).slice(2).padStart(64, "0");
// Bytes are padded at the end
let expected_hex = expected.slice(2).padEnd(64, "0");
expect(tx_call.result).equals("0x" + offset + length + expected_hex);
});
it("allows to call symbol", async function () {
let data = iFace.encodeFunctionData(
// action
"symbol",
[]
);
const tx_call = await customWeb3Request(context.web3, "eth_call", [
{
from: GENESIS_ACCOUNT,
value: "0x0",
gas: "0x10000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
},
]);
let expected = stringToHex("Local");
let offset = numberToHex(32).slice(2).padStart(64, "0");
let length = numberToHex(5).slice(2).padStart(64, "0");
// Bytes are padded at the end
let expected_hex = expected.slice(2).padEnd(64, "0");
expect(tx_call.result).equals("0x" + offset + length + expected_hex);
});
it("allows to call decimals", async function () {
let data = iFace.encodeFunctionData(
// action
"decimals",
[]
);
const tx_call = await customWeb3Request(context.web3, "eth_call", [
{
from: GENESIS_ACCOUNT,
value: "0x0",
gas: "0x10000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
},
]);
let expected = "0x" + numberToHex(12).slice(2).padStart(64, "0");
expect(tx_call.result).equals(expected);
});
it("allows to call getBalance", async function () {
let data = iFace.encodeFunctionData(
// action
"balanceOf",
[BALTATHAR]
);
const tx_call = await customWeb3Request(context.web3, "eth_call", [
{
from: GENESIS_ACCOUNT,
value: "0x0",
gas: "0x10000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
},
]);
let amount = new BN(100000000000000);
let amount_hex = "0x" + bnToHex(amount).slice(2).padStart(64, "0");
expect(tx_call.result).equals(amount_hex);
});
it("allows to call totalSupply", async function () {
let data = iFace.encodeFunctionData(
// action
"totalSupply",
[]
);
const tx_call = await customWeb3Request(context.web3, "eth_call", [
{
from: GENESIS_ACCOUNT,
value: "0x0",
gas: "0x10000",
gasPrice: GAS_PRICE,
to: assetAddress,
data: data,
},
]);
let amount = new BN(100000000000000);
let amount_hex = "0x" + bnToHex(amount).slice(2).padStart(64, "0");
expect(tx_call.result).equals(amount_hex);
});
},
true
);