Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minor security fixes and test updates #55

Merged
merged 8 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions .github/workflows/build.yml → .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
name: build
name: tests
env:
cli-id: anchor-v0.30.0-solana-1.18.8
on:
push:
branches:
- '*'
pull_request:
branches:
- '*'
- 'staging'
jobs:
build-cli-deps:
runs-on: ubicloud-standard-8
setup-tests:
runs-on: ubicloud-standard-16
steps:
- id: cache-cli-deps
uses: actions/cache@v2
Expand All @@ -33,9 +30,9 @@ jobs:
if: steps.cache-cli-deps.outputs.cache-hit != 'true'
run: cargo install --git https://github.com/bridgesplit/anchor anchor-cli --locked

build:
runs-on: ubicloud-standard-8
needs: [build-cli-deps]
run-tests:
runs-on: ubicloud-standard-16
needs: [setup-tests]
steps:
- id: cache-cli-deps
uses: actions/cache@v2
Expand Down
3 changes: 3 additions & 0 deletions clients/rwa-token-sdk/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
enableImmutableInstalls: false
}
8 changes: 4 additions & 4 deletions clients/rwa-token-sdk/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "@bridgesplit/rwa-token-sdk",
"version": "0.0.0",
"version": "0.0.1",
"description": "RWA Token SDK for the development of permissioned tokens on SVM blockchains.",
"homepage": "https://github.com/bridgesplit/rwa-token#readme",
"scripts": {
"test": "vitest run --testTimeout=120000",
"test": "vitest run --testTimeout=240000",
"lint": "eslint . --ext .ts"
},
"repository": {
Expand All @@ -30,12 +30,12 @@
"eslint-config-xo-typescript": "^3.0.0",
"typedoc": "^0.25.13",
"typescript": ">=5.0.0",
"vitest": "^1.5.0"
"vitest": "^1.5.2"
},
"author": "Standard Labs, Inc.",
"contributors": [
"Luke Truitt <[email protected]>",
"Bhargava Macha <[email protected]>",
"Bhargava Sai Macha <[email protected]>",
"Chris Hagedorn <[email protected]>"
],
"license": "MIT"
Expand Down
13 changes: 7 additions & 6 deletions clients/rwa-token-sdk/src/asset-controller/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Keypair,
PublicKey,
SystemProgram,
SYSVAR_INSTRUCTIONS_PUBKEY,
type TransactionInstruction,
} from "@solana/web3.js";
import {
Expand All @@ -23,7 +24,6 @@ import {
import {
type CommonArgs,
type IxReturn,
parseRemainingAccounts,
} from "../utils";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
Expand Down Expand Up @@ -149,10 +149,7 @@ export type TransferTokensArgs = {
from: string;
to: string;
amount: number;
authority: string;
decimals: number;
/** Optional parameter for transfer controls (policies) and privacy (identity). */
remainingAccounts?: string[];
} & CommonArgs;

/**
Expand Down Expand Up @@ -199,6 +196,11 @@ export async function getTransferTokensIx(
isWritable: false,
isSigner: false,
},
{
pubkey: SYSVAR_INSTRUCTIONS_PUBKEY,
isWritable: false,
isSigner: false,
},
{
pubkey: getExtraMetasListPda(args.assetMint),
isWritable: false,
Expand All @@ -210,7 +212,6 @@ export async function getTransferTokensIx(
isSigner: false,
},
];
remainingAccounts.push(...parseRemainingAccounts(args.remainingAccounts));
const ix = createTransferCheckedInstruction(
getAssociatedTokenAddressSync(
new PublicKey(args.assetMint),
Expand Down Expand Up @@ -289,7 +290,7 @@ export async function getSetupAssetControllerIxs(
): Promise<IxReturn> {
const mintKp = new Keypair();
const mint = mintKp.publicKey;
const updatedArgs = { ...args, assetMint: mint.toString() };
const updatedArgs = { ...args, assetMint: mint.toString(), signer: args.authority };
// Get asset registry create ix
const assetControllerCreateIx = await getCreateAssetControllerIx(
updatedArgs,
Expand Down
15 changes: 15 additions & 0 deletions clients/rwa-token-sdk/src/classes/PolicyEngine.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { type IxReturn } from "../utils";
import {
type AttachPolicyArgs,
DetachPolicyArgs,
getAttachToPolicyAccountIx,
getCreatePolicyAccountIx,
getDetachFromPolicyAccountIx,
getPolicyEnginePda,
} from "../policy-engine";
import { type RwaClient } from "./Client";
Expand Down Expand Up @@ -44,6 +46,19 @@ export class PolicyEngine {
return attachPolicyIx;
}

/**
* Asynchronously detaches a policy to the policy account.
* @param - {@link DetachPolicyArgs}
* @returns A Promise that resolves to the instructions to detach a policy.
* */
async detachPolicy(policyArgs: DetachPolicyArgs): Promise<IxReturn> {
const attachPolicyIx = await getDetachFromPolicyAccountIx(
policyArgs,
this.rwaClient.provider
);
return attachPolicyIx;
}

/**
* Retrieves the policy registry pda account for a specific asset mint.
* @param assetMint - The string representation of the asset's mint address.
Expand Down
2 changes: 2 additions & 0 deletions clients/rwa-token-sdk/src/data-registry/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { type AnchorProvider } from "@coral-xyz/anchor";
/** Represents arguments for creating an on chain data registry to store data accounts. */
export type CreateDataRegistryArgs = {
authority: string;
signer: string;
} & CommonArgs;

/**
Expand All @@ -31,6 +32,7 @@ export async function getCreateDataRegistryIx(
)
.accountsStrict({
payer: args.payer,
signer: args.signer,
assetMint: args.assetMint,
dataRegistry: getDataRegistryPda(args.assetMint),
systemProgram: SystemProgram.programId,
Expand Down
2 changes: 2 additions & 0 deletions clients/rwa-token-sdk/src/identity-registry/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { type AnchorProvider } from "@coral-xyz/anchor";
/** Represents arguments for creating an on identity registry on chain. */
export type CreateIdentityRegistryArgs = {
authority: string;
signer: string;
} & CommonArgs;

/**
Expand All @@ -33,6 +34,7 @@ export async function getCreateIdentityRegistryIx(
)
.accountsStrict({
payer: args.payer,
signer: args.signer,
assetMint: args.assetMint,
identityRegistryAccount: getIdentityRegistryPda(args.assetMint),
systemProgram: SystemProgram.programId,
Expand Down
14 changes: 5 additions & 9 deletions clients/rwa-token-sdk/src/policy-engine/data.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type AnchorProvider } from "@coral-xyz/anchor";
import { type PolicyEngineAccount, type PolicyAccount } from "./types";
import { getPolicyEnginePda, getPolicyEngineProgram } from "./utils";
import { getPolicyAccountPda, getPolicyEnginePda, getPolicyEngineProgram } from "./utils";

/**
* Retrieves policy engine account associated with a specific asset mint.
Expand All @@ -16,16 +16,12 @@ export async function getPolicyEngineAccount(assetMint: string, provider: Anchor
}

/**
* Retrieves all policy engine accounts for a specific asset mint.
* Retrieves the policy engine account for a specific asset mint.
* @param assetMint - The string representation of the asset mint.
* @returns A promise resolving to an array of {@link PolicyAccount}, or `undefined` if undefined doesn't exist.
*/
export async function getPolicyAccounts(assetMint: string, provider: AnchorProvider): Promise<PolicyAccount[] | undefined> {
export async function getPolicyAccount(assetMint: string, provider: AnchorProvider): Promise<PolicyAccount | undefined> {
const policyEngineProgram = getPolicyEngineProgram(provider);
const policyEnginePda = getPolicyEnginePda(assetMint);
const policyAccounts = await provider.connection.getProgramAccounts(policyEngineProgram.programId, {
filters:
[{ memcmp: { offset: 9, bytes: policyEnginePda.toBase58() } }],
});
return policyAccounts.map(account => policyEngineProgram.coder.accounts.decode("PolicyAccount", account.account.data));
const policyAccountPda = getPolicyAccountPda(assetMint);
return policyEngineProgram.account.policyAccount.fetch(policyAccountPda);
}
57 changes: 47 additions & 10 deletions clients/rwa-token-sdk/src/policy-engine/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { type AnchorProvider } from "@coral-xyz/anchor";
/** Represents the arguments required to create a policy engine account. */
export type CreatePolicyEngineArgs = {
authority: string;
signer: string;
} & CommonArgs;

/**
Expand All @@ -34,6 +35,7 @@ export async function getCreatePolicyEngineIx(
)
.accountsStrict({
payer: args.payer,
signer: args.signer,
assetMint: args.assetMint,
policyEngine: getPolicyEnginePda(args.assetMint),
systemProgram: SystemProgram.programId,
Expand All @@ -42,24 +44,59 @@ export async function getCreatePolicyEngineIx(
return ix;
}

/** Represents the arguments required to attach a policy to an assets. */
/** Represents the arguments required to attach a policy to an asset. */
export type AttachPolicyArgs = {
authority: string;
owner: string;
assetMint: string;
payer: string;
identityFilter: IdentityFilter;
policyType: PolicyType;
};

/** TODO: Cleanup unused helper function */
export function padIdentityLevels(levels: number[]): number[] {
const maxLevels = 10;
return levels.concat(new Array(maxLevels - levels.length).fill(0));
/** Represents the arguments required to detach a policy from an asset. */
export type DetachPolicyArgs = {
authority: string;
owner: string;
assetMint: string;
payer: string;
hash: string;
};

/**
* Generate instructions to connect am policy to an asset.
*
* This function constructs an instruction to attach a policy account to an asset
* using the provided arguments. It calls the policy engine program to attach the policy account,
* and returns the generated instruction along with the required signers.
*
* @param args {@link AttachPolicyArgs}
* @returns - {@link IxReturn}, a list of transaction instructions and a new key pair responsible to sign it.
*/
export async function getAttachToPolicyAccountIx(
args: AttachPolicyArgs,
provider: AnchorProvider
): Promise<IxReturn> {
const policyProgram = getPolicyEngineProgram(provider);
const policyAccount = getPolicyAccountPda(args.assetMint);
const ix = await policyProgram.methods
.attachToPolicyAccount(args.identityFilter, args.policyType)
.accountsStrict({
policyAccount,
signer: new PublicKey(args.authority),
payer: args.payer,
policyEngine: getPolicyEnginePda(args.assetMint),
systemProgram: SystemProgram.programId,
})
.instruction();
return {
ixs: [ix],
signers: [],
};
}


/**
* Generate instructions to connect an identity policy account to an asset.
* Generate instructions to detach an identity policy account to an asset.
*
* This function constructs an instruction to attach a policy account to an asset
* using the provided arguments. It creates a new policy account, calls the policy
Expand All @@ -69,14 +106,14 @@ export function padIdentityLevels(levels: number[]): number[] {
* @param args {@link AttachPolicyArgs}
* @returns - {@link IxReturn}, a list of transaction instructions and a new key pair responsible to sign it.
*/
export async function getAttachToPolicyAccountIx(
args: AttachPolicyArgs,
export async function getDetachFromPolicyAccountIx(
args: DetachPolicyArgs,
provider: AnchorProvider
): Promise<IxReturn> {
const policyProgram = getPolicyEngineProgram(provider);
const policyAccount = getPolicyAccountPda(args.assetMint);
const ix = await policyProgram.methods
.attachToPolicyAccount(args.identityFilter, args.policyType)
.detachFromPolicyAccount(args.hash)
.accountsStrict({
policyAccount,
signer: new PublicKey(args.authority),
Expand Down
Loading
Loading