@polkadot/util-crypto#encodeAddress TypeScript Examples

The following examples show how to use @polkadot/util-crypto#encodeAddress. 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: useAccounts.ts    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
useAccounts = (): Accounts => {
  const { dispatchAccount } = useUpdateAccountContext();
  const { dispatchChangeSourceTarget } = useUpdateSourceTarget();
  const sourceTarget = useSourceTarget();
  const { accounts } = useAccountContext();

  const setCurrentAccount = useCallback(
    (account, sourceChain) => {
      const accountKeyring = accounts.find(
        ({ address }) => encodeAddress(account, GENERIC_SUBSTRATE_PREFIX) === address
      );

      dispatchChangeSourceTarget(SourceTargetActionsCreators.switchChains(sourceChain));
      dispatchAccount(AccountActionCreators.setAccount(accountKeyring!, sourceTarget, sourceChain));
    },
    [accounts, dispatchAccount, dispatchChangeSourceTarget, sourceTarget]
  );
  return {
    accounts,
    setCurrentAccount
  };
}
Example #2
Source File: keyring.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * get address and avatar from mnemonic.
 */
async function addressFromMnemonic(mnemonic: string, ss58Format: number, cryptoType: KeypairType, derivePath: string) {
  let keyPair: KeyringPair;
  try {
    keyPair = keyring.addFromMnemonic(mnemonic + (derivePath || ""), {}, cryptoType);
    const address = encodeAddress(keyPair.publicKey, ss58Format);
    const icons = await account.genIcons([address]);
    return {
      address,
      svg: icons[0][1],
    };
  } catch (err) {
    return { error: err.message };
  }
}
Example #3
Source File: keyring.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * Generate a set of new mnemonic.
 */
async function gen(mnemonic: string, ss58Format: number, cryptoType: KeypairType, derivePath: string) {
  const key = mnemonic || mnemonicGenerate();
  if (!mnemonicValidate(key)) return null;

  const keyPair = keyring.addFromMnemonic(key + (derivePath || ""), {}, cryptoType || "sr25519");
  const address = encodeAddress(keyPair.publicKey, ss58Format || 0);
  const icons = await account.genIcons([address]);
  return {
    mnemonic: key,
    address,
    svg: icons[0][1],
  };
}
Example #4
Source File: spec.ts    From polkadot-launch with MIT License 6 votes vote down vote up
// Add additional authorities to chain spec in `session.keys`
export async function addAuthority(spec: string, name: string) {
	await cryptoWaitReady();

	const sr_keyring = new Keyring({ type: "sr25519" });
	const sr_account = sr_keyring.createFromUri(`//${nameCase(name)}`);
	const sr_stash = sr_keyring.createFromUri(`//${nameCase(name)}//stash`);

	const ed_keyring = new Keyring({ type: "ed25519" });
	const ed_account = ed_keyring.createFromUri(`//${nameCase(name)}`);

	const ec_keyring = new Keyring({ type: "ecdsa" });
	const ec_account = ec_keyring.createFromUri(`//${nameCase(name)}`);

	let key = [
		sr_stash.address,
		sr_stash.address,
		{
			grandpa: ed_account.address,
			babe: sr_account.address,
			im_online: sr_account.address,
			parachain_validator: sr_account.address,
			authority_discovery: sr_account.address,
			para_validator: sr_account.address,
			para_assignment: sr_account.address,
			beefy: encodeAddress(ec_account.publicKey),
		},
	];

	let rawdata = fs.readFileSync(spec);
	let chainSpec = JSON.parse(rawdata);

	let keys = getAuthorityKeys(chainSpec);
	keys.push(key);

	let data = JSON.stringify(chainSpec, null, 2);
	fs.writeFileSync(spec, data);
	console.log(`  ? Added Genesis Authority ${name}`);
}
Example #5
Source File: keyring.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * get address and avatar from rawSeed.
 */
async function addressFromRawSeed(rawSeed: string, ss58Format: number, cryptoType: KeypairType, derivePath: string) {
  let keyPair: KeyringPair;
  try {
    keyPair = keyring.addFromUri(rawSeed + (derivePath || ""), {}, cryptoType);
    const address = encodeAddress(keyPair.publicKey, ss58Format);
    const icons = await account.genIcons([address]);
    return {
      address,
      svg: icons[0][1],
    };
  } catch (err) {
    return { error: err.message };
  }
}
Example #6
Source File: address.ts    From bodhi.js with Apache License 2.0 6 votes vote down vote up
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 #7
Source File: index.ts    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
export function getTransactionDisplayPayload({
  payload,
  account,
  createType,
  sourceTargetDetails
}: PayloadInput): Output {
  const {
    sourceChainDetails: {
      chain: sourceChain,
      configs: { ss58Format }
    },
    targetChainDetails: { chain: targetChain }
  } = sourceTargetDetails;
  const payloadType = createType(sourceChain as keyof InterfaceTypes, 'OutboundPayload', payload);
  const payloadHex = payloadType.toHex();
  const callType = createType(targetChain as keyof InterfaceTypes, 'BridgedOpaqueCall', payload.call);
  const call = createType(targetChain as keyof InterfaceTypes, 'Call', callType.toHex());
  const formatedAccount = encodeAddress(account, ss58Format);

  const transactionDisplayPayload = {} as TransactionDisplayPayload;
  const { spec_version, weight, dispatch_fee_payment } = payload;
  transactionDisplayPayload.call = JSON.parse(call);
  transactionDisplayPayload.origin = {
    SourceAccount: formatedAccount
  };
  transactionDisplayPayload.weight = weight;

  transactionDisplayPayload.dispatch_fee_payment = dispatch_fee_payment;
  transactionDisplayPayload.spec_version = spec_version;
  return { transactionDisplayPayload, payloadHex };
}
Example #8
Source File: keyring.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * Add user's accounts to keyring incedence,
 * so user can use them to sign txs with password.
 * We use a list of ss58Formats to encode the accounts
 * into different address formats for different networks.
 */
async function initKeys(accounts: KeyringPair$Json[], ss58Formats: number[]) {
  await cryptoWaitReady();
  const res = {};
  ss58Formats.forEach((ss58) => {
    (<any>res)[ss58] = {};
  });

  accounts.forEach((i) => {
    // import account to keyring
    const keyPair = keyring.addFromJson(i);
    // then encode address into different ss58 formats
    ss58Formats.forEach((ss58) => {
      const pubKey = u8aToHex(keyPair.publicKey);
      (<any>res)[ss58][pubKey] = keyring.encodeAddress(keyPair.publicKey, ss58);
    });
  });
  return res;
}
Example #9
Source File: formatAccounts.ts    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
export default function formatAccounts(accounts: Array<KeyringPair>, ss58Format: number) {
  // TO-DO: This function lacks the  capabillity to filter accounts that exist only on specific chains.
  return accounts.map(({ meta, address }) => {
    const formatedAddress = encodeAddress(address, ss58Format);
    return {
      icon: 'user',
      key: formatedAddress,
      text: (meta.name as string).toLocaleUpperCase(),
      value: formatedAddress
    };
  });
}
Example #10
Source File: keyring.ts    From sdk with Apache License 2.0 6 votes vote down vote up
/**
 * estimate gas fee of an extrinsic
 */
async function txFeeEstimate(api: ApiPromise, txInfo: any, paramList: any[]) {
  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);
  }

  let sender = txInfo.sender.address;
  if (txInfo.proxy) {
    // wrap tx with recovery.asRecovered for proxy tx
    tx = api.tx.recovery.asRecovered(txInfo.sender.address, tx);
    sender = keyring.encodeAddress(hexToU8a(txInfo.proxy.pubKey));
  }
  const dispatchInfo = await tx.paymentInfo(sender);
  return dispatchInfo;
}
Example #11
Source File: TransactionContext.tsx    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
export function TransactionContextProvider(props: TransactionContextProviderProps): React.ReactElement {
  const { children = null } = props;
  const { account, senderAccountBalance, senderCompanionAccountBalance, companionAccount } = useAccountContext();
  const { action, isBridged } = useGUIContext();
  const {
    sourceChainDetails: {
      configs: { ss58Format }
    }
  } = useSourceTarget();
  const [transactionsState, dispatchTransaction] = useReducer(transactionReducer, initTransactionState);

  useResetTransactionState(action, dispatchTransaction);
  useEstimatedFeePayload(transactionsState, dispatchTransaction);
  useTransactionsStatus(transactionsState.transactions, transactionsState.evaluatingTransactions, dispatchTransaction);
  useSenderBalanceUpdates(senderAccountBalance, senderCompanionAccountBalance, dispatchTransaction);

  useEffect((): void => {
    account && dispatchTransaction(TransactionActionCreators.setSender(encodeAddress(account.address, ss58Format)));
  }, [account, companionAccount, ss58Format]);

  useEffect((): void => {
    action && dispatchTransaction(TransactionActionCreators.setAction(action));
  }, [action]);

  useEffect((): void => {
    !isBridged && dispatchTransaction(TransactionActionCreators.changeDispatchFeePayChain(PayFee.AtSourceChain));
  }, [isBridged]);

  return (
    <TransactionContext.Provider value={transactionsState}>
      <UpdateTransactionContext.Provider value={{ dispatchTransaction }}>{children}</UpdateTransactionContext.Provider>
    </TransactionContext.Provider>
  );
}
Example #12
Source File: SenderAccount.tsx    From parity-bridges-ui with GNU General Public License v3.0 6 votes vote down vote up
export default function SenderAccount({ handleClick, anchorEl }: Props) {
  const classes = useStyles();
  const { account, senderAccountBalance, senderBalanceAccountLoading } = useAccountContext();
  const { isBridged } = useGUIContext();
  const {
    sourceChainDetails: {
      configs: { ss58Format }
    }
  } = useSourceTarget();

  const open = Boolean(anchorEl);
  const id = open ? 'simple-popover' : undefined;

  return (
    <Box
      onClick={handleClick}
      p={1}
      className={cx(classes.accountMain, isBridged ? classes.withoutBottomBorderRadius : '')}
      id="test-sender-component"
    >
      <SelectLabel>Sender</SelectLabel>
      <Box display="flex">
        <div className={classes.account}>
          <AccountDisplay
            senderBalanceAccountLoading={senderBalanceAccountLoading}
            aria-describedby={id}
            friendlyName={account ? getName(account) : 'Select sender account'}
            address={account ? encodeAddress(account.address, ss58Format) : ''}
            balance={senderAccountBalance?.formattedBalance}
          />
        </div>
        <div className={classes.icon}>{open ? <ArrowDropUp /> : <ArrowDropDownIcon />}</div>
      </Box>
    </Box>
  );
}
Example #13
Source File: index.ts    From parachain-launch with Apache License 2.0 6 votes vote down vote up
getAddress = (val: string) => {
  try {
    const addr = decodeAddress(val);
    return encodeAddress(addr);
  } catch {}

  const keyring = new Keyring();
  const pair = keyring.createFromUri(`//${_.startCase(val)}`, undefined, 'sr25519');

  return pair.address;
}
Example #14
Source File: addressSwapper.ts    From commonwealth with GNU General Public License v3.0 6 votes vote down vote up
AddressSwapper = (options) => {
  if (!options.address) throw new Error('No address provided to swap');
  if (!options.currentPrefix) return options.address;
  if (isU8a(options.address) || isHex(options.address)) {
    throw new Error('address not in SS58 format');
  }
  // check if it is valid as an address
  let decodedAddress: Uint8Array;
  try {
    decodedAddress = decodeAddress(options.address);
  } catch (e) {
    throw new Error('failed to decode address');
  }
  // check if it is valid with the current prefix & reencode if needed
  const [valid, errorMsg] = checkAddress(options.address, options.currentPrefix);
  if (!valid) {
    try {
      return encodeAddress(decodedAddress, options.currentPrefix);
    } catch (e) {
      throw new Error('failed to reencode address');
    }
  } else {
    return options.address;
  }
}
Example #15
Source File: address_swapper.ts    From commonwealth with GNU General Public License v3.0 6 votes vote down vote up
AddressSwapper = (options: {
  address: string, currentPrefix: number,
}): string => {
  if (!options.address) throw new Error('No address provided to swap');
  if (!options.currentPrefix) return options.address;
  if (isU8a(options.address) || isHex(options.address)) {
    throw new Error('address not in SS58 format');
  }
  // check if it is valid as an address
  let decodedAddress: Uint8Array;
  try {
    decodedAddress = decodeAddress(options.address);
  } catch (e) {
    throw new Error('failed to decode address');
  }
  // check if it is valid with the current prefix & reencode if needed
  const [valid, errorMsg] = checkAddress(options.address, options.currentPrefix);
  if (!valid) {
    try {
      return encodeAddress(decodedAddress, options.currentPrefix);
    } catch (e) {
      throw new Error('failed to reencode address');
    }
  } else {
    return options.address;
  }
}
Example #16
Source File: address.ts    From subscan-multisig-react with Apache License 2.0 6 votes vote down vote up
export function convertToSS58(text: string, prefix: number, isShort = false): string {
  if (!text) {
    return '';
  }

  try {
    let address = encodeAddress(text, prefix);
    const length = 8;

    if (isShort) {
      address = address.substr(0, length) + '...' + address.substr(address.length - length, length);
    }

    return address;
  } catch (error) {
    return '';
  }
}
Example #17
Source File: index.ts    From parity-bridges-ui with GNU General Public License v3.0 5 votes vote down vote up
setLocalReceiver = (state: TransactionState, payload: ReceiverPayload): TransactionState => {
  const { unformattedReceiverAddress, sourceChainDetails } = payload;
  // Abstract this into a helper function
  const { isValid, formatFound } = getValidAddressFormat(unformattedReceiverAddress!);
  if (isValid) {
    const receiverAddress = encodeAddress(unformattedReceiverAddress!, sourceChainDetails.configs.ss58Format);
    const shouldEvaluatePayloadEstimatedFee = shouldCalculatePayloadFee(state, { receiverAddress });
    const transactionReadyToExecute = isReadyToExecute({ ...state, ...payload });
    if (formatFound === GENERIC) {
      return {
        ...state,
        unformattedReceiverAddress,
        receiverAddress,
        genericReceiverAccount: null,
        addressValidationError: null,
        showBalance: true,
        formatFound: GENERIC,
        transactionReadyToExecute,
        shouldEvaluatePayloadEstimatedFee
      };
    }
    if (formatFound === sourceChainDetails.configs.ss58Format) {
      return {
        ...state,
        unformattedReceiverAddress,
        receiverAddress: unformattedReceiverAddress,
        derivedReceiverAccount: null,
        genericReceiverAccount: null,
        addressValidationError: null,
        showBalance: true,
        formatFound: sourceChainDetails.chain,
        transactionReadyToExecute,
        shouldEvaluatePayloadEstimatedFee
      };
    }
  }

  return {
    ...state,
    addressValidationError: 'Invalid Address',
    unformattedReceiverAddress,
    receiverAddress: null,
    genericReceiverAccount: null,
    formatFound: null,
    transactionReadyToExecute: false,
    payloadEstimatedFeeLoading: false,
    shouldEvaluatePayloadEstimatedFee: false,
    estimatedSourceFee: null,
    estimatedTargetFee: null,
    payload: null
  };
}
Example #18
Source File: QrSigner.ts    From sdk with Apache License 2.0 5 votes vote down vote up
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 #19
Source File: Provider.ts    From evm-provider.js with Apache License 2.0 5 votes vote down vote up
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 #20
Source File: Args.tsx    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
// eslint-disable-next-line complexity
function formatAddressValue(value: string | string[], chain: Chain) {
  const encodeAddr = (addr: string) => {
    try {
      // eslint-disable-next-line no-magic-numbers
      const formatVal = addr.padStart(66, '0x');

      return encodeAddress(formatVal, +chain.ss58Format);
    } catch (err) {
      console.error('? ~ file: Args.tsx ~ line 57 ~ formatAddressValue ~ err', err);

      return addr;
    }
  };

  if (isString(value)) {
    // eslint-disable-next-line no-magic-numbers
    if (value.length < 12 && /^\d+$/.test(value)) {
      const registry = new TypeRegistry();

      registry.setChainProperties(
        registry.createType('ChainProperties', { ss58Format: +chain.ss58Format }) as ChainProperties
      );

      const ss58 = registry.createType('AccountIndex', +value).toString();

      return <SubscanLink address={ss58} copyable />;
    }
    // eslint-disable-next-line no-magic-numbers
    if (value.length > 60) {
      return <SubscanLink address={encodeAddr(value)} copyable />;
    }

    return <SubscanLink address={value} copyable />;
  }

  if (isArray(value)) {
    return (
      <>
        {value.map((item: string) => (
          <SubscanLink address={encodeAddr(item)} copyable key={item} />
        ))}
      </>
    );
  }

  return null;
}
Example #21
Source File: multisig.ts    From subscan-multisig-react with Apache License 2.0 5 votes vote down vote up
export function useMultisig(acc?: string) {
  const [multisigAccount, setMultisigAccount] = useState<KeyringAddress | null>(null);
  const { api, networkStatus, chain } = useApi();
  const { account } = useParams<{ account: string }>();
  const ss58Account = encodeAddress(account, Number(chain.ss58Format));

  const [inProgress, setInProgress] = useState<Entry[]>([]);
  const [loadingInProgress, setLoadingInProgress] = useState(false);
  const queryInProgress = useCallback(async () => {
    if (!api) {
      return;
    }

    setLoadingInProgress(true);

    const multisig = keyring.getAccount(acc ?? ss58Account);
    // Use different ss58 addresses
    (multisig?.meta.addressPair as KeyringJson[])?.forEach((key) => {
      key.address = convertToSS58(key.address, Number(chain.ss58Format));
    });

    const data = await api.query.multisig.multisigs.entries(multisig?.address);
    const result: Pick<Entry, 'when' | 'depositor' | 'approvals' | 'address' | 'callHash'>[] = data?.map((entry) => {
      const [address, callHash] = entry[0].toHuman() as string[];

      return {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        ...(entry[1] as unknown as any).toJSON(),
        address,
        callHash,
      };
    });

    const callInfos = await api?.query.multisig.calls.multi(result.map((item) => item.callHash || ''));
    // eslint-disable-next-line complexity
    const calls: Entry[] = callInfos?.map((callInfo, index) => {
      const call = callInfo.toJSON() as AnyJson[];

      if (!call) {
        return { ...result[index], callDataJson: {}, meta: {}, hash: result[index].callHash };
      }

      try {
        const callData = api.registry.createType('Call', call[0]);
        const { section, method } = api.registry.findMetaCall(callData.callIndex);
        const callDataJson = { ...callData.toJSON(), section, method };
        const hexCallData = call[0];
        const meta = api?.tx[callDataJson?.section][callDataJson.method].meta.toJSON();

        return { ...result[index], callDataJson, callData, meta, hash: result[index].callHash, hexCallData };
      } catch {
        return { ...result[index], callDataJson: {}, meta: {}, hash: result[index].callHash };
      }
    });

    setMultisigAccount(multisig || null);
    setInProgress(calls || []);
    setLoadingInProgress(false);
  }, [api, acc, ss58Account, chain]);

  useEffect(() => {
    if (networkStatus !== 'success') {
      return;
    }

    queryInProgress();
  }, [networkStatus, queryInProgress]);

  return {
    inProgress,
    multisigAccount,
    setMultisigAccount,
    queryInProgress,
    loadingInProgress,
  };
}
Example #22
Source File: parachain.ts    From polkadot-launch with MIT License 5 votes vote down vote up
export function parachainAccount(id: string) {
	let prefix = stringToHex("para");
	let encoded_id = bnToHex(parseInt(id), { isLe: true });
	let address_bytes = (prefix + hexStripPrefix(encoded_id)).padEnd(64 + 2, "0");
	let address = encodeAddress(address_bytes);

	return address;
}
Example #23
Source File: getDeriveAccount.ts    From parity-bridges-ui with GNU General Public License v3.0 5 votes vote down vote up
export default function getDeriveAccount({ ss58Format = 42, bridgeId, address }: Data): string {
  if (!address) {
    return address;
  }
  const input = [...compactAddLength(stringToU8a(accountDerivation)), ...bridgeId, ...decodeAddress(address)];
  return encodeAddress(blake2AsHex(Uint8Array.from(input)), ss58Format);
}
Example #24
Source File: useGenericAccount.ts    From parity-bridges-ui with GNU General Public License v3.0 5 votes vote down vote up
useGenericAccount = (value: string) => {
  const [selected, setSelected] = useState('');

  const { dispatchTransaction } = useUpdateTransactionContext();
  const {
    sourceChainDetails: { chain: sourceChain },
    targetChainDetails: {
      configs: targetConfigs,
      apiConnection: { api: targetApi }
    }
  } = useSourceTarget();

  const nativeAddress = encodeAddress(value, targetConfigs.ss58Format);
  const nativeState = useBalance(targetApi, nativeAddress, true);

  const companionAddress = getDeriveAccount({
    ss58Format: targetConfigs.ss58Format,
    address: value,
    bridgeId: getBridgeId(targetApi, sourceChain)
  });
  const companionState = useBalance(targetApi, companionAddress, true);

  const looseHelperAccount = useCallback(() => {
    setSelected('');
    dispatchTransaction(TransactionActionCreators.setReceiverAddress(null));
  }, [dispatchTransaction]);

  const setNativeAsTargetOrClear = useCallback(
    (address: string, addressKind: AddressKind) => {
      if (selected) {
        looseHelperAccount();
        return;
      }
      setSelected(addressKind);
      dispatchTransaction(TransactionActionCreators.setReceiverAddress(address));
    },
    [dispatchTransaction, looseHelperAccount, selected]
  );

  const setNativeAsTarget = useCallback(() => setNativeAsTargetOrClear(nativeAddress, AddressKind.NATIVE), [
    nativeAddress,
    setNativeAsTargetOrClear
  ]);
  const setCompanionAsTarget = useCallback(() => setNativeAsTargetOrClear(companionAddress, AddressKind.COMPANION), [
    companionAddress,
    setNativeAsTargetOrClear
  ]);

  const shortGenericAddress = shorterItem(value);

  return {
    selected,
    shortGenericAddress,
    setNativeAsTarget,
    setCompanionAsTarget,
    nativeAddress,
    nativeState,
    companionAddress,
    companionState
  };
}
Example #25
Source File: accounts.ts    From subsocial-js with GNU General Public License v3.0 5 votes vote down vote up
toSubsocialAddress = (address?: string) => {
  if (!address || !isAddress(address)) return undefined

  return encodeAddress(decodeAddress(address), 28)
}
Example #26
Source File: useApiCalls.ts    From parity-bridges-ui with GNU General Public License v3.0 4 votes vote down vote up
useApiCalls = (): ApiCallsContextType => {
  const { sourceChainDetails, targetChainDetails } = useSourceTarget();
  const {
    apiConnection: { api: sourceApi },
    chain: sourceChain
  } = sourceChainDetails;
  const { keyringPairs, keyringPairsReady } = useKeyringContext();
  const { getValuesByChain } = useChainGetters();

  const createType = useCallback(
    (chain, type, data) => {
      const { api } = getValuesByChain(chain);
      return api.registry.createType(type, data);
    },
    [getValuesByChain]
  );

  const stateCall = useCallback(
    (chain: string, methodName: string | Text, data: string | Uint8Array | Bytes, at) => {
      const { api } = getValuesByChain(chain);

      const params: [string | Text, string | Uint8Array | Bytes] = [methodName, data];
      if (at) {
        params.push(at);
      }

      return api.rpc.state.call<Codec>(...params);
    },
    [getValuesByChain]
  );

  const internalTransfer = useCallback(
    async (dispatchers, transfersData) => {
      const { dispatchTransaction, dispatchMessage } = dispatchers;
      const { receiverAddress, transferAmount, account } = transfersData;
      const type = TransactionTypes.INTERNAL_TRANSFER;

      const id = Date.now().toString();
      dispatchTransaction(TransactionActionCreators.setTransactionRunning(true));

      try {
        const transfer = sourceApi.tx.balances.transfer(receiverAddress, transferAmount);
        const options: Partial<SignerOptions> = {
          nonce: -1
        };
        let sourceAccount: string | KeyringPair = account;
        if (account.meta.isInjected) {
          const injector = await web3FromSource(account.meta.source as string);
          options.signer = injector.signer;
          sourceAccount = account.address;
        }

        const transactionDisplayPayload = {
          sourceAccount: account?.address || sourceAccount,
          transferAmount: transferAmount.toNumber(),
          receiverAddress
        };

        const unsub = await transfer.signAndSend(sourceAccount, { ...options }, async ({ status }) => {
          const steps = createEmptyInternalSteps(sourceChain);
          if (status.isReady) {
            dispatchTransaction(
              TransactionActionCreators.createTransactionStatus({
                block: null,
                blockHash: null,
                deliveryBlock: null,
                id,
                input: transferAmount,
                messageNonce: null,
                receiverAddress,
                sourceAccount: account.address,
                senderName: getName(account),
                sourceChain,
                status: TransactionStatusEnum.IN_PROGRESS,
                targetChain: '',
                type,
                transactionDisplayPayload,
                payloadHex: transfer.toHex(),
                steps
              })
            );
          }

          if (status.isBroadcast) {
            dispatchMessage(MessageActionsCreators.triggerInfoMessage({ message: 'Transaction was broadcasted' }));
            dispatchTransaction(TransactionActionCreators.reset());
          }

          if (status.isInBlock) {
            try {
              const res = (await sourceApi.rpc.chain.getBlock(status.asInBlock)) as SignedBlock;
              const block = res.block.header.number.toString();
              dispatchTransaction(
                TransactionActionCreators.updateTransactionStatus(
                  {
                    block,
                    blockHash: status.asInBlock.toString()
                  },
                  id
                )
              );
            } catch (e) {
              if (e instanceof Error) {
                logger.error(e.message);
                throw new Error('Issue reading block information.');
              }
            }
          }

          if (status.isFinalized) {
            dispatchTransaction(
              TransactionActionCreators.updateTransactionStatus(
                {
                  status: TransactionStatusEnum.FINALIZED
                },
                id
              )
            );
            logger.info(`Transaction finalized at blockHash ${status.asFinalized}`);
            unsub();
          }
        });
      } catch (e) {
        if (e instanceof Error) {
          dispatchMessage(MessageActionsCreators.triggerErrorMessage({ message: e.message }));
          logger.error(e.message);
        }
      } finally {
        dispatchTransaction(TransactionActionCreators.setTransactionRunning(false));
      }
    },
    [sourceApi.rpc.chain, sourceApi.tx.balances, sourceChain]
  );

  const updateSenderAccountsInformation = useCallback(
    async (dispatchAccount) => {
      const formatBalanceAddress = (data: any, api: ApiPromise): BalanceState => {
        return {
          chainTokens: data.registry.chainTokens[0],
          formattedBalance: formatBalance(data.free, {
            decimals: api.registry.chainDecimals[0],
            withUnit: api.registry.chainTokens[0],
            withSi: true
          }),
          free: data.free
        };
      };

      if (!keyringPairsReady || !keyringPairs.length) {
        return {};
      }

      const getAccountInformation = async (sourceRole: any, targetRole: any) => {
        const {
          apiConnection: { api: sourceApi },
          chain: sourceChain,
          configs: sourceConfigs
        } = sourceRole;
        const {
          apiConnection: { api: targetApi },
          configs: targetConfigs
        } = targetRole;

        const accounts = await Promise.all(
          keyringPairs.map(async ({ address, meta }) => {
            const sourceAddress = encodeAddress(address, sourceConfigs.ss58Format);
            const toDerive = {
              ss58Format: targetConfigs.ss58Format,
              address: sourceAddress || '',
              bridgeId: getBridgeId(targetApi, sourceChain)
            };
            const { data } = await sourceApi.query.system.account(sourceAddress);
            const sourceBalance = formatBalanceAddress(data, sourceApi);

            const companionAddress = getDeriveAccount(toDerive);
            const { data: dataCompanion } = await targetApi.query.system.account(companionAddress);
            const targetBalance = formatBalanceAddress(dataCompanion, targetApi);

            const name = (meta.name as string).toLocaleUpperCase();

            return {
              account: { address: sourceAddress, balance: sourceBalance, name },
              companionAccount: { address: companionAddress, balance: targetBalance, name }
            };
          })
        );

        return accounts;
      };

      const sourceAddresses = await getAccountInformation(sourceChainDetails, targetChainDetails);
      const targetAddresses = await getAccountInformation(targetChainDetails, sourceChainDetails);

      dispatchAccount(
        AccountActionCreators.setDisplaySenderAccounts({
          [sourceChainDetails.chain]: sourceAddresses,
          [targetChainDetails.chain]: targetAddresses
        })
      );
    },
    [keyringPairs, keyringPairsReady, sourceChainDetails, targetChainDetails]
  );

  return { createType, stateCall, internalTransfer, updateSenderAccountsInformation };
}
Example #27
Source File: QrSigner.ts    From sdk with Apache License 2.0 4 votes vote down vote up
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 #28
Source File: index.ts    From parachain-launch with Apache License 2.0 4 votes vote down vote up
generateRelaychainGenesisFile = (config: Config, path: string, output: string) => {
  const relaychain = config.relaychain;

  if (!relaychain) {
    return fatal('Missing relaychain');
  }
  if (!relaychain.chain) {
    return fatal('Missing relaychain.chain');
  }
  if (!relaychain.image) {
    return fatal('Missing relaychain.image');
  }

  const spec = getChainspec(relaychain.image, relaychain.chain);

  // clear authorities
  const runtime = spec.genesis.runtime.runtime_genesis_config || spec.genesis.runtime;

  const sessionKeys = runtime.session.keys;
  sessionKeys.length = 0;

  // add authorities from config
  const keyring = new Keyring();
  for (const { name } of config.relaychain.nodes) {
    const srAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'sr25519');
    const srStash = keyring.createFromUri(`//${_.startCase(name)}//stash`, undefined, 'sr25519');
    const edAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'ed25519');
    const ecAcc = keyring.createFromUri(`//${_.startCase(name)}`, undefined, 'ecdsa');

    const key = [
      srStash.address,
      srStash.address,
      {
        grandpa: edAcc.address,
        babe: srAcc.address,
        im_online: srAcc.address,
        parachain_validator: srAcc.address,
        authority_discovery: srAcc.address,
        para_validator: srAcc.address,
        para_assignment: srAcc.address,
        beefy: encodeAddress(ecAcc.publicKey),
      },
    ];

    sessionKeys.push(key);
  }

  // additional patches
  if (config.relaychain.runtimeGenesisConfig) {
    const hrmp = config.relaychain.runtimeGenesisConfig.hrmp;
    if (hrmp) {
      hrmp.preopenHrmpChannels = hrmp.preopenHrmpChannels.map((channel) => {
        if (!Array.isArray(channel)) {
          return [channel.sender, channel.recipient, channel.maxCapacity, channel.maxMessageSize];
        } else {
          return channel;
        }
      });
    }
    _.merge(runtime, config.relaychain.runtimeGenesisConfig);
  }

  // genesis parachains
  for (const parachain of config.parachains) {
    const { wasm, state } = exportParachainGenesis(parachain, output);
    if (!parachain.id) {
      return fatal('Missing parachains[].id');
    }
    const para = [
      parachain.id,
      {
        genesis_head: state,
        validation_code: wasm,
        parachain: parachain.parachain,
      },
    ];
    runtime.paras.paras.push(para);
  }

  const tmpfile = `${shell.tempdir()}/${config.relaychain.chain}.json`;
  fs.writeFileSync(tmpfile, jsonStringify(spec));

  exec(
    `docker run --rm -v "${tmpfile}":/${config.relaychain.chain}.json ${config.relaychain.image} build-spec --raw --chain=/${config.relaychain.chain}.json --disable-default-bootnode > ${path}`
  );

  shell.rm(tmpfile);

  console.log('Relaychain genesis generated at', path);
}
Example #29
Source File: magic.ts    From commonwealth with GNU General Public License v3.0 4 votes vote down vote up
export function useMagicAuth(models: DB) {
  // allow magic login if configured with key
  if (MAGIC_API_KEY) {
    // TODO: verify we are in a community that supports magic login
    const magic = new Magic(MAGIC_API_KEY);
    passport.use(new MagicStrategy({ passReqToCallback: true }, async (req, user, cb) => {
      // determine login location
      let chain, error;
      if (req.body.chain || req.body.community) {
        [ chain, error ] = await validateChain(models, req.body);
        if (error) return cb(error);
      }
      const registrationChain = chain;

      // fetch user data from magic backend
      let userMetadata: MagicUserMetadata;
      try {
        userMetadata = await magic.users.getMetadataByIssuer(user.issuer);
      } catch (e) {
        return cb(new Error('Magic fetch failed.'));
      }

      // check if this is a new signup or a login
      const existingUser = await models.User.scope('withPrivateData').findOne({
        where: {
          email: userMetadata.email,
        },
        include: [{
          model: models.Address,
          where: { wallet_id: WalletId.Magic },
          required: false,
        }]
      });

      // unsupported chain -- client should send through old email flow
      if (!existingUser && (!registrationChain?.base || !MAGIC_SUPPORTED_BASES.includes(registrationChain.base))) {
        return cb(new Error('Unsupported magic chain.'));
      }

      if (!existingUser) {
        const ethAddress = userMetadata.publicAddress;
        let polkadotAddress;

        // always retrieve the polkadot address for the user regardless of chain
        try {
          const polkadotResp = await request
            // eslint-disable-next-line max-len
            .get(`https://api.magic.link/v1/admin/auth/user/public/address/get?issuer=did:ethr:${userMetadata.publicAddress}`)
            .set('X-Magic-Secret-key', MAGIC_API_KEY)
            .accept('json');
          if (polkadotResp.body?.status !== 'ok') {
            throw new Error(polkadotResp.body?.message || 'Failed to fetch polkadot address');
          }
          const polkadotRespAddress = polkadotResp.body?.data?.public_address;

          // convert to chain-specific address based on ss58 prefix, if we are on a specific
          // polkadot chain. otherwise, encode to edgeware.
          if (registrationChain.ss58_prefix) {
            polkadotAddress = encodeAddress(polkadotRespAddress, registrationChain.ss58_prefix);
          } else {
            polkadotAddress = encodeAddress(polkadotRespAddress, 7); // edgeware SS58 prefix
          }
        } catch (err) {
          return cb(new Error(err.message));
        }

        const result = await sequelize.transaction(async (t) => {
          // create new user and unverified address if doesn't exist
          const newUser = await models.User.createWithProfile(models, {
            email: userMetadata.email,
            emailVerified: true,
          }, { transaction: t });

          // create an address on their selected chain
          let newAddress: AddressInstance;
          if (registrationChain.base === ChainBase.Substrate) {
            newAddress = await models.Address.create({
              address: polkadotAddress,
              chain: registrationChain.id,
              verification_token: 'MAGIC',
              verification_token_expires: null,
              verified: new Date(), // trust addresses from magic
              last_active: new Date(),
              user_id: newUser.id,
              profile_id: (newUser.Profiles[0] as ProfileAttributes).id,
              wallet_id: WalletId.Magic,
            }, { transaction: t });

            // if they selected a substrate chain, create an additional address on ethereum
            // and auto-add them to the eth forum
            const ethAddressInstance = await models.Address.create({
              address: ethAddress,
              chain: 'ethereum',
              verification_token: 'MAGIC',
              verification_token_expires: null,
              verified: new Date(), // trust addresses from magic
              last_active: new Date(),
              user_id: newUser.id,
              profile_id: (newUser.Profiles[0] as ProfileAttributes).id,
              wallet_id: WalletId.Magic
            }, { transaction: t });

            await models.Role.create({
              address_id: ethAddressInstance.id,
              chain_id: 'ethereum',
              permission: 'member',
            });
          } else {
            newAddress = await models.Address.create({
              address: ethAddress,
              chain: registrationChain.id,
              verification_token: 'MAGIC',
              verification_token_expires: null,
              verified: new Date(), // trust addresses from magic
              last_active: new Date(),
              user_id: newUser.id,
              profile_id: (newUser.Profiles[0] as ProfileAttributes).id,
              wallet_id: WalletId.Magic,
            }, { transaction: t });

            // if they selected an eth chain, create an additional address on edgeware
            // and auto-add them to the forum
            const edgewareAddressInstance = await models.Address.create({
              address: polkadotAddress,
              chain: 'edgeware',
              verification_token: 'MAGIC',
              verification_token_expires: null,
              verified: new Date(), // trust addresses from magic
              last_active: new Date(),
              user_id: newUser.id,
              profile_id: (newUser.Profiles[0] as ProfileAttributes).id,
              wallet_id: WalletId.Magic,
            }, { transaction: t });

            await models.Role.create({
              address_id: edgewareAddressInstance.id,
              chain_id: 'edgeware',
              permission: 'member',
            }, { transaction: t });
          }

          if (req.body.chain) await models.Role.create({
            address_id: newAddress.id,
            chain_id: req.body.chain,
            permission: 'member',
          }, { transaction: t });

          // Automatically create subscription to their own mentions
          await models.Subscription.create({
            subscriber_id: newUser.id,
            category_id: NotificationCategories.NewMention,
            object_id: `user-${newUser.id}`,
            is_active: true,
          }, { transaction: t });

          // Automatically create a subscription to collaborations
          await models.Subscription.create({
            subscriber_id: newUser.id,
            category_id: NotificationCategories.NewCollaboration,
            object_id: `user-${newUser.id}`,
            is_active: true,
          }, { transaction: t });

          // create token with provided user/address
          await models.SsoToken.create({
            issuer: userMetadata.issuer,
            issued_at: user.claim.iat,
            address_id: newAddress.id,
          }, { transaction: t });

          return newUser;
        });

        // re-fetch user to include address object
        const newUser = await models.User.findOne({
          where: {
            id: result.id,
          },
          include: [ models.Address ],
        });
        return cb(null, newUser);
      } else if (existingUser.Addresses?.length > 0) {
        // each user should only ever have one token issued by Magic
        const ssoToken = await models.SsoToken.findOne({
          where: {
            issuer: user.issuer
          },
          include: [{
            model: models.Address,
            where: { address: user.publicAddress },
            required: true,
          }]
        });
        // login user if they registered via magic
        if (user.claim.iat <= ssoToken.issued_at) {
          console.log('Replay attack detected.');
          return cb(null, null, {
            message: `Replay attack detected for user ${user.publicAddress}}.`,
          });
        }
        ssoToken.issued_at = user.claim.iat;
        await ssoToken.save();
        console.log(`Found existing user: ${JSON.stringify(existingUser)}`);
        return cb(null, existingUser);
      } else {
        // error if email exists but not registered with magic
        console.log('User already registered with old method.');
        return cb(null, null, {
          message: `Email for user ${user.issuer} already registered`
        });
      }
    }));
  }
}