Skip to content

Commit

Permalink
Adding support for solana intent (transfer) (#3198)
Browse files Browse the repository at this point in the history
  • Loading branch information
silva-fj authored Dec 11, 2024
1 parent 21d10ff commit bbb8612
Show file tree
Hide file tree
Showing 25 changed files with 8,717 additions and 4,090 deletions.
10 changes: 9 additions & 1 deletion common/primitives/core/src/intent.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{AccountId, Balance};
use crate::{AccountId, Address32, Balance};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::H160;
Expand All @@ -18,6 +18,8 @@ pub enum Intent {
SystemRemark(BoundedVec<u8, ConstU32<MAX_REMARK_LEN>>),
#[codec(index = 3)]
TransferNative(TransferNative),
#[codec(index = 4)]
TransferSolana(TransferSolana),
}

#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
Expand All @@ -39,3 +41,9 @@ pub struct TransferNative {
pub to: AccountId,
pub value: Balance,
}

#[derive(Encode, Decode, Debug, Clone, PartialEq, Eq, MaxEncodedLen, TypeInfo)]
pub struct TransferSolana {
pub to: Address32,
pub value: u64,
}
2 changes: 1 addition & 1 deletion tee-worker/identity/client-api/parachain-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "dist/src/index.js",
"module": "dist/src/index.js",
"sideEffects": false,
"version": "0.9.20-next.9",
"version": "0.9.20-next.10",
"scripts": {
"clean": "rm -rf dist build node_modules",
"update-metadata": "curl -s -H \"Content-Type: application/json\" -d '{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}' http://localhost:9944 > prepare-build/litentry-parachain-metadata.json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export default {
CallEthereum: "IntentCallEthereum",
SystemRemark: "Bytes",
TransferNative: "IntentTransferNative",
TransferSolana: "IntentTransferSolana",
},
},
IntentTransferEthereum: {
Expand All @@ -20,6 +21,10 @@ export default {
to: "AccountId32",
value: "u128",
},
IntentTransferSolana: {
to: "[u8; 32]",
value: "u64",
},

/**
* AccountStore
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@litentry/client-sdk",
"description": "This package provides helpers for dApps to interact with the Litentry Protocol.",
"version": "1.0.0-next.6",
"version": "1.0.0-next.7",
"license": "GPL-3.0-or-later",
"dependencies": {},
"devDependencies": {
"@polkadot/rpc-provider": "^10.9.1"
},
"peerDependencies": {
"@litentry/parachain-api": "0.9.20-next.9",
"@litentry/parachain-api": "0.9.20-next.10",
"@litentry/sidechain-api": "0.9.20-next.8",
"@litentry/chaindata": "*",
"@polkadot/api": "^10.9.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { remark } from './remark.request';
export { transferNative } from './transfer-native.request';
export { transferEthereum } from './transfer-ethereum.request';
export { callEthereum } from './call-ethereum.request';
export { transferSolana } from './transfer-solana.request';

export { createAccountStore } from './create-account-store.request';
export { getIdGraph } from './get-id-graph.request';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { createRequestType } from '../type-creators/request';
import type { JsonRpcRequest } from '../util/types';

/**
* Transfers Ethereum to another account on the Litentry Parachain.
* Transfers ETH to another account on Ethereum.
*
* @returns {Promise<Object>} - A promise that resolves to an object containing the payload to signature
* (if applicable) and a send function.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { assert, hexToU8a } from '@polkadot/util';

import type { ApiPromise } from '@polkadot/api';
import type {
LitentryIdentity,
TrustedCallResult,
WorkerRpcReturnValue,
} from '@litentry/parachain-api';

import { enclave } from '../enclave';
import { codecToString } from '../util/codec-to-string';
import { createPayloadToSign } from '../util/create-payload-to-sign';
import { createTrustedCallType } from '../type-creators/trusted-call';
import { createRequestType } from '../type-creators/request';

import type { JsonRpcRequest } from '../util/types';

/**
* Transfers SOL to another account on Solana.
*
* @returns {Promise<Object>} - A promise that resolves to an object containing the payload to signature
* (if applicable) and a send function.
* @returns {string} [payloadToSign] - The payload to sign if who is not an email identity.
* @returns {Function} send - A function to send the request to the Enclave.
* @returns {Promise<Object>} send.args - The arguments required to send the request.
* @returns {string} send.args.authentication - The authentication string. If who is
* an email identity, this is the email verification code. If the who is not an email identity,
* this is the signed payload.
*/
export async function transferSolana(
/** Litentry Parachain API instance from Polkadot.js */
api: ApiPromise,
data: {
/** The user's omniAccount. Use `createLitentryIdentityType` helper to create this struct */
omniAccount: LitentryIdentity;
/** The user's account. Use `createLitentryIdentityType` helper to create this struct */
who: LitentryIdentity;
/** Solana address destination */
to: string;
/** Amount to send in lamports */
amount: bigint;
}
): Promise<{
payloadToSign?: string;
send: (args: { authentication: string }) => Promise<{
response: WorkerRpcReturnValue;
blockHash: string;
extrinsicHash: string;
}>;
}> {
const { who, omniAccount } = data;

assert(omniAccount.isSubstrate, 'OmniAccount must be a Substrate identity');

const shard = await enclave.getShard(api);
const shardU8 = hexToU8a(shard);

const { call } = await createTrustedCallType(api.registry, {
method: 'request_intent',
params: {
who,
intent: api.createType('Intent', {
TransferSolana: api.createType('IntentTransferSolana', {
to: data.to,
value: data.amount,
}),
}),
},
});

const nonce = await api.rpc.system.accountNextIndex(omniAccount.asSubstrate);

const send = async (args: {
authentication: string;
}): Promise<{
response: WorkerRpcReturnValue;
blockHash: string;
extrinsicHash: string;
}> => {
// prepare and encrypt request

const request = await createRequestType(api, {
sender: who,
authentication: args.authentication,
call,
nonce,
shard: shardU8,
});

// send the request to the Enclave
const rpcRequest: JsonRpcRequest = {
jsonrpc: '2.0',
method: 'author_submitNativeRequest',
params: [request.toHex()],
};

const [response] = await enclave.send(api, rpcRequest); // we expect 1 response only

const result: TrustedCallResult = api.createType(
'TrustedCallResult',
response.value
);

if (result.isErr) {
throw new Error(codecToString(result.asErr));
}

if (!result.asOk.isExtrinsicReport) {
throw new Error('Unexpected response type');
}

const { extrinsic_hash, block_hash } = result.asOk.asExtrinsicReport;

return {
response,
extrinsicHash: extrinsic_hash.toString(),
blockHash: block_hash.toString(),
};
};

if (who.isEmail) {
return { send };
}

const payloadToSign = createPayloadToSign({
who,
call,
nonce,
shard: shardU8,
});

return {
payloadToSign,
send,
};
}
Loading

0 comments on commit bbb8612

Please sign in to comment.