Skip to content

Commit

Permalink
Beta ipAsset and permission modules (P0) (#47)
Browse files Browse the repository at this point in the history
* change name

* add tests

* update test

* update read only tests

* address some tests

* fix some tests

* remove waitForTxn for setPermission

* Remove unused variables

* fix unit test coverage

* Lint clean up

---------

Co-authored-by: Ze Huang <[email protected]>
  • Loading branch information
allenchuang and edisonz0718 authored Jan 27, 2024
1 parent d53145e commit f70cc84
Show file tree
Hide file tree
Showing 32 changed files with 746 additions and 333 deletions.
9 changes: 5 additions & 4 deletions packages/core-sdk/src/abi/accessController.abi.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { formatAbi } from "abitype";
import { getAddress } from "viem";

import AccessControllerABI from "./json/AccessController.abi";
import errorsJson from "./json/Errors.json";

export const AccessControllerRaw = AccessControllerABI;
export const AccessControllerReadable = formatAbi(AccessControllerRaw);
export const ErrorsAbi = errorsJson;

export const AccessControllerABImerged = [...AccessControllerABI, ...ErrorsAbi];

export const AccessControllerConfig = {
abi: AccessControllerRaw,
abi: AccessControllerABImerged,
address: getAddress(
process.env.ACCESS_CONTROLLER || process.env.NEXT_PUBLIC_ACCESS_CONTROLLER || "",
),
Expand Down
6 changes: 6 additions & 0 deletions packages/core-sdk/src/abi/ipAccountImpl.abi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import IPAccountImplABI from "./json/IPAccountImpl.abi";
import errorsJson from "./json/Errors.json";

export const ErrorsAbi = errorsJson;

export const IPAccountImplMerged = [...IPAccountImplABI, ...ErrorsAbi];
37 changes: 37 additions & 0 deletions packages/core-sdk/src/abi/json/AccessController.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,41 @@ export default [
stateMutability: "nonpayable",
type: "function",
},
{
anonymous: false,
inputs: [
{
indexed: true,
internalType: "address",
name: "ipAccount",
type: "address",
},
{
indexed: true,
internalType: "address",
name: "signer",
type: "address",
},
{
indexed: true,
internalType: "address",
name: "to",
type: "address",
},
{
indexed: false,
internalType: "bytes4",
name: "func",
type: "bytes4",
},
{
indexed: false,
internalType: "uint8",
name: "permission",
type: "uint8",
},
],
name: "PermissionSet",
type: "event",
},
] as const;
2 changes: 1 addition & 1 deletion packages/core-sdk/src/abi/json/IIPAccountRegistry.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default [
type: "uint256",
},
],
name: "ipAccount",
name: "ipAsset",
outputs: [
{
internalType: "address",
Expand Down
2 changes: 1 addition & 1 deletion packages/core-sdk/src/abi/json/IPAccountRegistry.abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default [
type: "uint256",
},
],
name: "ipAccount",
name: "ipAsset",
outputs: [
{
internalType: "address",
Expand Down
2 changes: 1 addition & 1 deletion packages/core-sdk/src/abi/sdkEntities.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[
"ipAccount",
"ipAsset",
"registerRootIp",
"registerDerivativeIp",
"addPolicy",
Expand Down
25 changes: 19 additions & 6 deletions packages/core-sdk/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import { TransactionReadOnlyClient } from "./resources/transactionReadOnly";
import { HTTP_TIMEOUT } from "./constants/http";
import { Client, ReadOnlyClient } from "./types/client";
import { PlatformClient } from "./utils/platform";
import { IPAccountClient } from "./resources/ipAccount";
import { IPAccountReadOnlyClient } from "./resources/ipAccountReadOnly";
import { ModuleReadOnlyClient } from "./resources/moduleReadOnly";
import { TaggingClient } from "./resources/tagging";
import { TaggingReadOnlyClient } from "./resources/taggingReadOnly";
import { IPAssetClient } from "./resources/ipAsset";
import { IPAssetReadOnlyClient } from "./resources/ipAssetReadOnly";
import { PermissionClient } from "./resources/permission";
import { PermissionReadOnlyClient } from "./resources/permissionReadOnly";

if (typeof process !== "undefined") {
dotenv.config();
Expand All @@ -28,7 +30,8 @@ export class StoryClient {
private readonly rpcClient: PublicClient;
private readonly wallet?: WalletClient;

private _ipAccount: IPAccountClient | IPAccountReadOnlyClient | null = null;
private _ipAccount: IPAssetClient | IPAssetReadOnlyClient | null = null;
private _permission: PermissionClient | PermissionReadOnlyClient | null = null;
private _transaction: TransactionClient | TransactionReadOnlyClient | null = null;
private _platform: PlatformClient | null = null;
private _module: ModuleReadOnlyClient | null = null;
Expand Down Expand Up @@ -88,16 +91,26 @@ export class StoryClient {
return new StoryClient(config, false) as Client;
}

public get ipAccount(): IPAccountClient | IPAccountReadOnlyClient {
public get ipAsset(): IPAssetClient | IPAssetReadOnlyClient {
if (this._ipAccount === null) {
this._ipAccount = this.isReadOnly
? new IPAccountReadOnlyClient(this.httpClient, this.rpcClient)
: new IPAccountClient(this.httpClient, this.rpcClient, this.wallet!);
? new IPAssetReadOnlyClient(this.httpClient, this.rpcClient)
: new IPAssetClient(this.httpClient, this.rpcClient, this.wallet!);
}

return this._ipAccount;
}

public get permission(): PermissionClient | PermissionReadOnlyClient {
if (this._permission === null) {
this._permission = this.isReadOnly
? new PermissionReadOnlyClient(this.httpClient, this.rpcClient)
: new PermissionClient(this.httpClient, this.rpcClient, this.wallet!);
}

return this._permission;
}

/**
* Getter for the transaction client. The client is lazily created when
* this method is called.
Expand Down
8 changes: 4 additions & 4 deletions packages/core-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ export { TransactionClient } from "./resources/transaction";
export { PlatformClient } from "./utils/platform";
export { AddressZero, HashZero } from "./constants/common";

export { IPAccountClient } from "./resources/ipAccount";
export { IPAccountReadOnlyClient } from "./resources/ipAccountReadOnly";
export { AccessControlClient } from "./resources/accessControl";
export { AccessControlReadOnlyClient } from "./resources/accessControlReadOnly";
export { TaggingReadOnlyClient } from "./resources/taggingReadOnly";
export { ModuleReadOnlyClient } from "./resources/moduleReadOnly";
export { IPAssetClient } from "./resources/ipAsset";
export { IPAssetReadOnlyClient } from "./resources/ipAssetReadOnly";
export { PermissionClient } from "./resources/permission";
export { PermissionReadOnlyClient } from "./resources/permissionReadOnly";

export type { StoryConfig, StoryReadOnlyConfig } from "./types/config";
export type { Client, ReadOnlyClient } from "./types/client";
Expand Down
53 changes: 0 additions & 53 deletions packages/core-sdk/src/resources/accessControl.ts

This file was deleted.

15 changes: 0 additions & 15 deletions packages/core-sdk/src/resources/accessControlReadOnly.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
import { AxiosInstance } from "axios";
import { PublicClient, WalletClient, getAddress } from "viem";

// import { handleError } from "../utils/errors";
import { IPAccountReadOnlyClient } from "./ipAccountReadOnly";
import { IPAssetReadOnlyClient } from "./ipAssetReadOnly";
import { handleError } from "../utils/errors";
import { IPAccountRegistryConfig } from "../abi/ipAccountRegistry.abi";
import {
RegisterDerivativeIpRequest,
RegisterDerivativeIpResponse,
RegisterRootIpRequest,
RegisterRootIpResponse,
addPolicyRequest,
addPolicyResponse,
// addPolicyToIpRequest,
// addPolicyToIpResponse,
} from "../types/resources/ipAccount";
} from "../types/resources/ipAsset";
import { parseToBigInt, waitTxAndFilterLog } from "../utils/utils";
import { RegistrationModuleConfig } from "../abi/registrationModule.abi";
import { LicenseRegistryConfig } from "../abi/licenseRegistry.abi";
// import { HashZero } from "../constants/common";

export class IPAccountClient extends IPAccountReadOnlyClient {
export class IPAssetClient extends IPAssetReadOnlyClient {
private readonly wallet: WalletClient;

constructor(httpClient: AxiosInstance, rpcClient: PublicClient, wallet: WalletClient) {
Expand Down Expand Up @@ -101,40 +94,40 @@ export class IPAccountClient extends IPAccountReadOnlyClient {
}

// TODO: move to License resource
public async createPolicy(request: addPolicyRequest): Promise<addPolicyResponse> {
try {
const { request: call } = await this.rpcClient.simulateContract({
...LicenseRegistryConfig,
functionName: "addPolicy",
args: [
{
frameworkId: parseToBigInt(request.frameworkId),
mintingParamValues: request.mintingParamValues.map((add) => getAddress(add)),
activationParamValues: request.activationParamValues.map((add) => getAddress(add)),
needsActivation: request.needsActivation,
linkParentParamValues: request.linkParentParamValues.map((add) => getAddress(add)),
},
], // TODO: add args
});
// public async createPolicy(request: addPolicyRequest): Promise<addPolicyResponse> {
// try {
// const { request: call } = await this.rpcClient.simulateContract({
// ...LicenseRegistryConfig,
// functionName: "addPolicy",
// args: [
// {
// frameworkId: parseToBigInt(request.frameworkId),
// mintingParamValues: request.mintingParamValues.map((add) => getAddress(add)),
// activationParamValues: request.activationParamValues.map((add) => getAddress(add)),
// needsActivation: request.needsActivation,
// linkParentParamValues: request.linkParentParamValues.map((add) => getAddress(add)),
// },
// ], // TODO: add args
// });

const txHash = await this.wallet.writeContract(call);
// TODO: need an emitted event
// if (request.txOptions?.waitForTransaction) {
// const targetLog = await waitTxAndFilterLog(this.rpcClient, txHash, {
// ...IPAccountRegistryConfig,
// eventName: "IPAccountRegistered",
// });
// return { txHash: txHash, policyId: targetLog?.args.account.toString() };
// } else {
return { txHash: txHash };
// }
} catch (error) {
handleError(error, "Failed to register derivative IP");
}
}
// const txHash = await this.wallet.writeContract(call);
// // TODO: need an emitted event
// // if (request.txOptions?.waitForTransaction) {
// // const targetLog = await waitTxAndFilterLog(this.rpcClient, txHash, {
// // ...IPAccountRegistryConfig,
// // eventName: "IPAccountRegistered",
// // });
// // return { txHash: txHash, policyId: targetLog?.args.account.toString() };
// // } else {
// return { txHash: txHash };
// // }
// } catch (error) {
// handleError(error, "Failed to register derivative IP");
// }
// }

// TODO: move to License resource
// public async addPolicyToIp(request: addPolicyToIpRequest): Promise<addPolicyToIpResponse> {
// // TODO: use getIpAccount to get the ipId
// TODO: use getIpAccount to get the ipId
// }
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { AxiosInstance } from "axios";
import { PublicClient } from "viem";
import { PublicClient, isAddress } from "viem";

import {
GetIpAccountRequest,
GetIpAccountResponse,
ListIpAccountRequest,
ListIpAccountResponse,
} from "../types/resources/ipAccount";
GetIpAssetRequest,
GetIpAssetResponse,
ListIpAssetRequest,
ListIpAssetResponse,
} from "../types/resources/ipAsset";
import { handleError } from "../utils/errors";
import { isIntegerString } from "../utils/utils";

/**
* IPAssetReadOnlyClient allows you to view and search IP Assets on Story Protocol.
*/
export class IPAccountReadOnlyClient {
export class IPAssetReadOnlyClient {
protected readonly httpClient: AxiosInstance;
protected readonly rpcClient: PublicClient;

Expand All @@ -28,13 +27,13 @@ export class IPAccountReadOnlyClient {
* @param request - the request object for getting an IP Asset.
* @returns the response object the contains the fetched IP Asset.
*/
public async get(request: GetIpAccountRequest): Promise<GetIpAccountResponse> {
public async get(request: GetIpAssetRequest): Promise<GetIpAssetResponse> {
try {
if (!isIntegerString(request.ipId)) {
throw new Error(`Invalid chain id. Must be an integer. But get: ${request.ipId}`);
if (!isAddress(request.ipId)) {
throw new Error(`Invalid ip id. Must be an address. But get: ${request.ipId}`);
}
const response = await this.httpClient.get(`/protocol/ipaccount/${request.ipId}`);
return response.data as GetIpAccountResponse;
const response = await this.httpClient.get(`/accounts/${request.ipId}`);
return response.data as GetIpAssetResponse;
} catch (error: unknown) {
handleError(error, "Failed to get IP account");
}
Expand All @@ -45,10 +44,10 @@ export class IPAccountReadOnlyClient {
*
* @returns the response object that contains results from listing query.
*/
public async list(request?: ListIpAccountRequest): Promise<ListIpAccountResponse> {
public async list(request?: ListIpAssetRequest): Promise<ListIpAssetResponse> {
try {
const response = await this.httpClient.post(`/protocol/ipaccount`, request || {});
return response.data as ListIpAccountResponse;
const response = await this.httpClient.post(`/accounts`, request || {});
return response.data as ListIpAssetResponse;
} catch (error) {
handleError(error, "Failed to list IP Asset.");
}
Expand Down
Loading

0 comments on commit f70cc84

Please sign in to comment.