npm package: @soundsright/sdk
Description: soundsright chain sdk
Author: u404
Latest version: 0.2.8

# `@soundsright/sdk`

> @soundsright sdk 功能库

## Example
[Example](https://res.lyrra.io/site/sdk/example/index.html)

## 安装
```bash
npm install @soundsright/sdk;
```
## 快速开始

```js
import SDK from "@soundsright/sdk";

const sdk = new SDK({ env: 'dev' });
```
## 初始化
### 创建实例初始化
```js
const sdk = new SDK(options?);
```
### 初始化的options选项
```js
{
  env?: Env, // 环境设置。默认值：'dev', 可选值：'dev' | 'test' | 'pre' | 'prod'
  requestHandler?: RequestHandler,  // 请求委托函数，主要用于service模块。通常情况下无须手动配置，默认使用基于axios的XHR，在某些特殊的应用场景下，可能需要手动指定委托。
  supportedChainId?: number // 指定链id，指定后合约交互时会自动验证当前钱包所在的链。也可以不在初始化时指定，使用sdkInstance.chain.setSupportedChainId设置。
}
```
#### 特殊用法 - 定制RequestHandler
方法的签名：  
```ts
export declare type RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
export declare type RequestHeaders = {
    'Content-Type'?: string;
    'Authorization'?: string;
    [x: string]: string | number | boolean | undefined | null;
};
export declare type RequestOptions = {
    url: string;
    method?: RequestMethod;
    headers?: RequestHeaders;
    params?: Record<string, any>;
    data?: Record<string, any>;
    [x: string]: any;
};
export declare type RequestResult = {
    [x: string]: any;
};
export declare type RequestHandler = (options: RequestOptions) => Promise<RequestResult>;
```
自定义的requestHandler例子：
```js
// 基于window.fetch 实现一个requestHandler
const requestHandler = async ({ url, method, headers, params, data, ...opts }) => {
  const res = await window.fetch(`${url}${params?`?${qs.stringify(params)}`:''}`, {
    method,
    headers,
    body: data && JSON.stringify(data),
    ...opts
  });
  return res.json();
}
```

## 功能模块
目前集成的主要功能模块有：  
- [auth](#auth模块)，基础功能模块，用于实现第三方授权登录及钱包登录
- [connector](#connector模块)，基础功能模块，用于实现钱包连接
- [service](#service模块)，基础功能模块，实现与服务器接口交互
- [user](#user模块)，业务功能模块，实现用户登录、统一处理token、用户信息等
- [chain](#chain模块)，基础功能模块，实现链上合约操作
- [share](#share模块)，基础功能模块，实现分享功能
- [invite](#invite模块)，基础功能模块，实现邀请人的基础操作
- contracts，合约abi集合模块
- [nftMarket](#nftmarket模块)，业务功能模块，封装了与nft市场交互的业务逻辑

### auth模块
基础功能模块，用于实现第三方授权登录及钱包登录  
支持的第三方登录方式：Google、Facebook、Twitter  
```js
// Facebook 授权
const authResult = await sdk.auth.authByFacebook();
// authResult = { type: "Facebook", token: [access_token] }

// Google 授权
const authResult = await  sdk.auth.authByGoogle();
// authResult = { type: "Google", token: [access_token] }

// Twitter 授权
const authResult = await sdk.auth.authByTwitter();
// authResult = { type: "Twitter", token: [oauth_token], verifier: [oauth_verifier] }

// Wallet 连接签名
const authResult = await sdk.auth.authByWallet(options?);
// options = { 
//   connectType?: "MetaMask" 或 "WalletConnect"，若sdk.connector已连接，则无须指定，仅在sdk.connector未连接或需要更换连接类型时指定，将调用connector进行钱包连接
//   signMessage: 自定义的签名源消息，如："Welcome to Lyrra!",
//   afterConnect: (state: ConnectState) => Promise<void> | void
// }
// authResult = { 
//   type: "Wallet", 
//   token: 等同于signature,
//   signature: 签名值,
//   message: 源消息,
//   walletAddr: 用户地址,
// }

// 第三方平台授权，根据第三方类型
const authResult = await sdk.auth.authByThirdPlatform(type); // type: 'Google' | 'Facebook' | 'Twitter'
```
### connector模块
基础功能模块，用于实现钱包连接，及钱包连接状态的监听，是链操作的基础
支持的钱包连接方式：MetaMask（浏览器插件方式）、WalletConnect（App方式）
```js
// 使用MetaMask方式连接浏览器插件钱包
await sdk.connector.connect("MetaMask");
// 使用WalletConnect方式连接App钱包
await sdk.connector.connect("WalletConnect");
// 尝试以上次连接方式连接钱包
await sdk.connector.tryLastConnect();

// 获取连接的状态数据
const { account, chainId, provider, signer, connected } = sdk.connector.state;
// 获取当前连接的类型
const { type } = sdk.connector;
// type可能为："MetaMask" | "WalletConnect" | undefined

// 切换链
await sdk.connector.switchChain(newChainId);

// 增加新的token
await sdk.connector.addToken({ "0x123124...", "USDC", 6 });

// 监听连接状态事件
sdk.connector.on(event, handler); 

// event包括：
// - change，统一状态变化事件，任何状态变化都会触发该事件
// - connect，新连接建立时触发。MetaMask在切换不同类型的链时，也可能触发，比如：从 ethereum 切换到 polygon
// - disconnect，断开连接时触发。MetaMask在切换不同类型的链时，也可能触发，比如：从 ethereum 切换到 polygon
// - accountsChanged，用户切换钱包地址时触发
// - chainChanged，用户切换链时触发
// - uriAvailable，仅WalletConnect方式生成连接uri时触发。

// handler的参数e：
// e.event，仅在change触发时会传入该字段，值为"connect"、"accountsChanged"等具体事件名
// e的其他字段完全与connector.state一致，包括：account, chainId, provider, signer, connected

// 高级用法：
// 设置自定义缓存对象。
sdk.connector.setCache(storage); 
// storage 对象必须参考localStorage实现，即具备get和set方法。

// 注册自定义uri处理程序，主要用于WalletConnect方式中，定制弹窗界面。
sdk.connector.registUriHandler(handler);
// handler的函数声明为：(uri: string, disconnect: () => void) => () => void; 即：
// handler的参数为：uri, disconnect，其中uri用于展示给用户，帮助建立连接，disconnect是个函数，用于在用户取消连接时，断开连接，由于WalletConnect机制问题，这是必要的。
// handler的返回值是：() => void，即一个函数。该函数应该是一个取消处理程序的函数，比如：关闭当前正在显示的弹窗。
// WalletConnect在连接成功或钱包app内用户取消连接的情况下，会执行该函数。如果无须任何操作，可以返回一个空函数。
```  
#### ConnectorHelper 帮助方法
某些场景下，可能需要对connector做一些特殊的定制，其中一个需求是定制WalletConnect的弹窗界面，这里提供了一些帮助方法，用于快速实现功能  
```js
// 引入
import { ConnectorHelper } from "@soundsright/connector";

// 使用uri，唤起app。该方法主要用于安卓中。
ConnectorHelper.openUri(uri); 
// 使用uri，及相应app钱包配置信息，唤起app。该方法主要用于pc或ios中。walletConfig可由下面的方法获取。
ConnectorHelper.openAppUri(uri, walletConfig);

// 获取IOS中支持的钱包app列表，返回值为：walletConfig[]，whiteList参数为app名称的string[]
const walletConfigs = await ConnectorHelper.getIOSWalletConfigs(whiteList?);

// 获取pc中支持的钱包app列表，返回值为：walletConfig[]，whiteList参数为app名称的string[]
const walletConfigs = await ConnectorHelper.getDesktopWalletConfigs(whiteList?);

// 【不常用】设置fetch请求委托。用于非浏览器环境的特殊定制。
ConnectorHelper.setFetchHandler(fetchHandler);
```

### service模块
基础功能模块，实现与服务器接口交互  
```js

// 核心方法，发送到网关的请求
const data = await sdk.service.request(options);
// options选项：
// RequestOptions = {
//   url: string; // 凡是到网关的请求，url只写path即可
//   method?: RequestMethod; // 
//   headers?: RequestHeaders;
//   params?: Record<string, any>;
//   data?: Record<string, any>;
//   [x: string]: any; // 其他参数由RequestHandler自行处理
// };
// 
// RequestMethod = 'get' | 'post' | 'put' | 'delete' | 'head' | 'patch';
// RequestHeaders = {
//   'Content-Type'?: string;  // 默认统一为'application/json'，如果某服务或接口不一致，则需要手动指定
//   'Authorization'?: string;  // 如果使用user进行用户登录，则无须手动处理登录态的header
//   [x: string]: string | number | boolean | undefined | null;
// };
// 返回值：
// 网关接口的统一返回格式为：{ code, data?, msg }。函数的正常返回值为data字段值。
// 若接口内部错误，或网络异常，会抛出 ServiceError，e.name = 'ServiceError'，e.code = 接口返回的code或网络异常-1，e.message = 接口返回的msg
// user模块会对用户token失效等接口错误，进行拦截处理。但对于接口需要用户登录，但用户token无效时，会抛出UserError，e.name = 'UserError'。具体参考user模块。
// 请求示例：
// const res = await sdk.service.request({ url: '/ucenter/user/login', method: 'post', data: { type: 'Facebook', token: 'xxxxxxxxxxx...' } });
// console.log('登录成功', res);



// 简化方法，发送get请求
sdk.service.get(url: string, params?: Record<string, any>, headers?: RequestHeaders): Promise<any>;
// 请求示例：获取用户信息
// const user = await sdk.service.get('/ucenter/user/info', {}, { Authorization: 'xxxxxxx' });

// 简化方法，发送post请求
sdk.service.post(url: string, data?: Record<string, any>, headers?: RequestHeaders): Promise<any>;
// 请求示例：刷新accessToken
// const res = await this.service.post('/ucenter/user/refreshToken', {}, { refreshToken: 'xxxxxx' });

// 设置统一的请求header
sdk.service.setHeaders({ 'X-Request-CSRF': "123" });

// 移除全部自定义的公共请求header
sdk.service.removeHeaders(): void;

// 设置一个公共的请求拦截处理器，具体见下方例子
sdk.service.onBeforeRequest(handler: BeforeRequestHandler);

// 设置一个公共的返回值拦截处理器，具体见下方说明
sdk.service.onBeforeResponse(handler: BeforeResponseHandler);


/**
 * 下单 - 目前仅用于法币支付时
 * @param skuId - 商品skuId
 * @param payChannel - 支付渠道，传入PayChannel枚举或对应的数字值 - enum PayChannel { Checkout = 1 }
 * @param channelOptions - 渠道参数，每个渠道都有自己的要求。对于Checkout 传入 { payType: 1, countryCode: number - 国家代码, userAddress: string - 用户地址 }，可参考服务端文档
 * @returns 订单号和支付链接等字段 - { orderNo: string, payUrl: string }
 */
sdk.service.nft.createOrder(skuId: string, payChannel: PayChannel, channelOptions?: object): Promise<{ orderNo: string, payUrl: string }>;

/**
 * 查询订单状态 - 目前仅用于法币支付时
 * @param orderNo - 订单号
 * @returns 订单号和订单状态 - { orderNo: string, orderStatus: number }，对应的orderStatus值有：1-未支付、2-已过期、3-已支付、4-上链成功、5-购买完成
 */
sdk.service.nft.queryOrderStatus(orderNo: string | number): Promise<{ orderNo: string, orderStatus: number }>;


```
#### 设置公共请求拦截处理器
示例：拦截请求，统一处理token
```ts
sdk.service.onBeforeRequest((options) => {
  // options参数就是 RequestOptions 包含了请求的所有信息
  const headers = {
    Authorization: this.accessToken || '',
    ...options.headers,
  };
  // 拦截器处理后必须返回经过处理的options
  return { ...options, headers };
});
```
#### 设置公共的返回值拦截处理器
可以用来统一处理接口错误，弹出错误提示等。  
示例：拦截接口错误，弹出错误信息
```ts
sdk.service.onBeforeResponse(async (req, res) => {
  alert(`请求出错：${res.msg}`);
  // 注意对于用户登录状态的错误，包括accessToken失效或为空、refreshToken过期等，由user模块中注册的拦截器处理。
});
```
### user模块
业务功能模块，实现用户登录、统一处理token、用户信息等  
用户模块会根据用户登录状态对service模块实现一定的逻辑处理。
- 在用户登录成功时，向service请求模块注入header - Authorization: accessToken
- 在service模块发送请求时，若accessToken失效，则用户模块会静默进行token的刷新，并重新请求
- 若刷新时refreshToken失效，则会触发事件"tokenExpired"，可以监听该事件统一处理
基础用法：
```js
try {
  const user = await sdk.user.loginByThirdPlatform('Google');
  ...
} catch (e) {
  alert(e.message);
}

```
用户信息的完整定义字段：（由接口定义，可能会更新）
```ts
type User = {
  UserCode: string,   // 一般对前端无用
  NewUser: boolean,   // 是否是新注册用户
  WalletAddr: string | undefined,  // 钱包地址
  NickName: string | undefined,  // 用户昵称
  Picture: string | undefined,  // 用户头像
  Phone: string | undefined,  // 用户手机号
  Email: string | undefined  // 用户邮箱
}
```

方法列表：
```js
/**
 * 通过第三方平台登录
 * @param type - 第三方登录类型：'Google' | 'Facebook' | 'Twitter'
 * @returns 用户信息
 */
loginByThirdPlatform(type: ThirdPlatformAuthType): Promise<any>;
/**
 * 通过钱包连接和签名登录
 * @param options - 钱包授权的选项
 * ```ts
 * {
 *   connectType?: ConnectType枚举或"MetaMask"|"WalletConnect",
 *   signMessage?: 签名消息,
 *   afterConnect: (state: ConnectState) => Promise<void> | void
 * }
 * @returns 用户信息
 * ```
 */
loginByWallet(options?: WalletAuthOptions): Promise<any>;
/**
 * 通过cookie记录的token进行登录
 * @returns 用户信息
 */
loginByCookie(): Promise<any>;
/**
 * 设置是否记住用户登录状态
 * @param remember - 是否记住用户登录状态
 * @param days - 记住的天数，默认为7天
 */
setRememberState(remember: boolean, days?: number): void;
/**
 * 查询记住用户状态的天数
 * @returns number，返回记住的天数。如果为0，则仅在Session期有效。
 */
getRememberDays(): number;
/**
 * 查询是否记住用户的状态
 * @returns boolean
 */
getRememberState(): boolean;
/**
 * 刷新用户Token
 * @returns
 * ```ts
 * { accessToken: string, refreshToken: string }
 * ```
 */
refresh(): Promise<any>;
/**
 * 获取当前登录的用户基本信息
 * @returns 包括 { UserCode, NickName, Picture, Email, Phone, WalletAddr, NewUser }
 */
getCurrentUser(): any;
/**
 * 用户退出
 */
logout(): Promise<void>;
/**
 * 查询用户是否登录
 * @returns boolean
 */
isLogin(): boolean;
/**
 * 查询用户是否已经绑定钱包
 * @returns boolean
 */
isWalletBound(): boolean;
/**
 * 绑定第三方平台账号
 * @param type - 第三方登录类型：'Google' | 'Facebook' | 'Twitter'
 * @returns 用户信息
 */
bindThirdPlatform(type: ThirdPlatformAuthType): Promise<any>;
/**
 * 通过钱包连接和签名绑定钱包
 * @param options - 钱包授权的选项
 * ```ts
 * {
 *   connectType?: ConnectType枚举或"MetaMask"|"WalletConnect",
 *   signMessage?: 签名消息
 * }
 * @returns 用户信息
 * ```
 */
bindWallet(options?: WalletAuthOptions): Promise<any>;
/**
 * 检查用户是否具备执行合约的条件。若不符合条件，则抛出相应的异常 - 该方法应作为执行合约的前置检测方法（模板方法）
 * Error类型有：
 * - UnauthorizedError，用户未登录，需要弹出登录窗口
 * - WalletNotBoundError，用户未绑定钱包，需要弹出绑定钱包
 * - WalletNotConnectedError，用户未连接钱包，需要弹出钱包连接
 * - WalletNotMatchError，用户已连接的钱包地址与绑定的钱包地址不匹配
 * 可以使用try catch 来处理相应的错误，可以通过error.name 来方便的判定类型。
 * 在项目中结合界面操作逻辑，对该方法做进一步封装
 * ```ts
 * try {
 *   sdk.user.checkUserWeb3Condition();
 * } catch (e) {
 *  if(e.name === 'UnauthorizedError') {
 *    // do something
 *  }
 *  ...
 * }
 * ```
 */
checkUserWeb3Condition(): void;
/**
 * 监听用户模块触发的事件，目前包括以下事件：
 * 'tokenExpired' - 在调用需要用户token的接口，但本地token不存在或已失效时触发，无参数。监听该事件可以用来弹出用户登录的UI。
 * 'loginSuccess' - 登录成功并获取到用户信息时触发，事件参数为user对象。监听该事件可以统一处理用户登录成功的状态。
 * 'logout' - 用户退出时触发，无参数。监听该事件可以统一处理用户退出状态。
 * 'userUpdate' - 用户更新时触发，事件参数为用户对象。监听该事件可以处理用户更新的状态。如：钱包绑定更新。注意：绑定第三方账号，并不会触发该更新。
 */ 
on(event, handler): void;

// 示例：
sdk.user.on("tokenExpired", () => {
  // 弹出用户登录界面
});
sdk.user.on("loginSuccess", (user) => {
  // 用户信息处理
});
sdk.user.on("logout", () => {});
sdk.user.on("userUpdate", (user) => {
  // 用户信息更新
});

```

### chain模块
基础功能模块，实现链上合约操作  
```ts
// sdk.chain
getContract(address: string, abi: ContractInterface): Contract;
getUncheckedContract(address: string, abi: ContractInterface): Contract;
getLocalChain(chainId: number): LocalChain;  // 获取一个使用本地网络provider构造的chain实例，可以无需连接钱包直接执行一些查询方法
setSupportedChainId(chainId: number): void;
checkChain(): Promise<void>;
signMessage(message: string): Promise<string>;
signTypedMessage(domain: SignDomain, types: SignMessageTypes, value: SignMessageValue): any;
getBalance(account: string): Promise<string>;
checkTransaction(tx: any): Promise<boolean>;
tryTransaction(txPromise: Promise<any>): Promise<boolean>;

// sdk.chain.local - 一个使用本地网络provider构造的chain实例，用于无需连接钱包直接执行一些查询方法。
// 只有指定supportedChainId之后，才能获取该实例。可以通过sdk初始化时或sdk.chain.setSupportedChainId(chainId)来设置链
// 跟sdk.chain一样具有一些预置的模块：sdk.chain.local.nft、sdk.chain.local.token，但需要注意的是，只能使用其中的查询方法
getContract(address: string, abi: ContractInterface): Contract;
getBalance(address: string): Promise<string>;
tryGet(txPromise: Promise<any>): Promise<any>;
checkTransaction(tx: any): Promise<boolean>;
tryTransaction(txPromise: Promise<any>): Promise<boolean>;
setLocalProvider(chainId?: number): void;

// sdk.chain.nft
buyAndMint(address: string, tokenId: string, to: string, tokenURI: string, skuInfo: SkuInfoV1, v: number, r: string, s: string, overrides?: ContractWriteMethodOverrides): Promise<void>;
ownerOf(address: string, tokenId: string): Promise<string>;

// sdk.chain.token
approve(address: string, account: string, spender: string, amount: string): Promise<void>;
balanceOf(address: string, account: string): Promise<string>;
decimals(address: string): Promise<number>;
compareAmount(amount1: string, amount2: string): Promise<1 | -1 | 0>;
isBalanceEnough(address: string, account: string, amount: string): Promise<boolean>;
```

### share模块
基础功能模块，实现分享功能
```ts
/**
 * 获取分享链接
 * @param shareParams - 分享文案及描述：
 * ```ts
 * type ShareParams = {
 *   title: string,  // 标题文字
 *   description: string,  // 描述文字
 *   image?: string,  // 头图
 *   url?: string,  // 跳转目标url，若不传默认跳转到 https://www.lyrra.io。
 *   text?: string,  // 推荐语，分享到twitter时会显示
 *   inviter?: string, // 邀请人（用户编码），若传入则将邀请人拼接到url中
 *   short?: boolean, // 是否使用短链形式分享。默认为true
 * }
 * ```
 * @returns 返回链接url
 */
getShareUrl(params: ShareParams): Promise<string>;
/**
 * 分享到指定平台
 * @param platform - 平台类型：enum SharePlatform { Facebook: "Facebook", Twitter: "Twitter" }
 * @param shareParams - 分享文案及描述：
 * ```ts
 * type ShareParams = {
 *   title: string,  // 标题文字
 *   description: string,  // 描述文字
 *   image?: string,  // 头图
 *   url?: string,  // 跳转目标url，若不传默认跳转到 https://www.lyrra.io。
 *   text?: string,  // 推荐语，可为空
 *   inviter?: string, // 邀请人（用户编码），若传入则将邀请人拼接到url中
 *   short?: boolean, // 是否使用短链形式分享。默认为true
 * }
 * ```
 * @param windowOptions - 分享窗口的配置，一般无须配置
 * @returns 打开的分享窗口
 */
shareTo(platform: SharePlatform, shareParams: ShareParams, windowOptions?: OpenWindowOptions): Promise<Window>;
/**
 * 分享到Facebook
 * @param shareParams - 分享文案及描述：
 * ```ts
 * type ShareParams = {
 *   title: string,  // 标题文字
 *   description: string,  // 描述文字
 *   image?: string,  // 头图
 *   url?: string,  // 跳转目标url，若不传默认跳转到 https://www.lyrra.io。
 *   text?: string,  // 推荐语，可为空
 *   inviter?: string, // 邀请人（用户编码），若传入则将邀请人拼接到url中
 *   short?: boolean, // 是否使用短链形式分享。默认为true
 * }
 * ```
 * @param windowOptions - 分享窗口的配置，一般无须配置
 * @returns 打开的分享窗口
 */
shareToFacebook(shareParams: ShareParams, windowOptions?: OpenWindowOptions): Promise<Window>;
/**
 * 分享到Twitter
 * @param shareParams - 分享文案及描述：
 * ```ts
 * type ShareParams = {
 *   title: string,  // 标题文字
 *   description: string,  // 描述文字
 *   image?: string,  // 头图
 *   url?: string,  // 跳转目标url，若不传默认跳转到 https://www.lyrra.io。
 *   text?: string,  // 推荐语，可为空
 *   inviter?: string, // 邀请人（用户编码），若传入则将邀请人拼接到url中
 *   short?: boolean, // 是否使用短链形式分享。默认为true
 * }
 * ```
 * @param windowOptions - 分享窗口的配置，一般无须配置
 * @returns 打开的分享窗口
 */
shareToTwitter(shareParams: ShareParams, windowOptions?: OpenWindowOptions): Promise<Window>;
/**
 * 复制分享链接
 * @param shareParams - 分享文案及描述：
 * ```ts
 * type ShareParams = {
 *   title: string,  // 标题文字
 *   description: string,  // 描述文字
 *   image?: string,  // 头图
 *   url?: string,  // 跳转目标url，若不传默认跳转到 https://www.lyrra.io。
 *   text?: string,  // 推荐语，分享到twitter时会显示
 *   inviter?: string, // 邀请人（用户编码），若传入则将邀请人拼接到url中
 *   short?: boolean, // 是否使用短链形式分享。默认为true
 * }
 * ```
 * @returns 返回链接url
 */
copyShareUrl(shareParams: ShareParams): Promise<string>;
/**
 * 复制链接
 * @param url - 普通文本链接
 */
copyUrl(url: string): void;
/**
 * 设置请求方法，特殊情况下使用
 * @param handler - RequestHandler
 */
setRequestHandler(handler: RequestHandler): void;

// 示例：
const shareConfig = {
  title: "这是标题",
  description: "这是描述",
  image: "https://www.disney.co.jp/content/dam/disney/images/studio/buzzlightyear/ogp/ogp_buzzlightyear_01.jpg",
  url: "https://www.lyrra.io",
  text: "这是推荐语"
};

sdk.share.shareToFacebook(shareConfig); // 打开小窗口调起Facebook分享
```

### invite模块
基础功能模块，实现邀请人的基础操作
```ts
/**
 * 从url中获取邀请人
 * @returns 邀请人（用户编码）
 */
getInviterFromUrl(): string | undefined;
/**
 * 将url中的邀请人缓存到cookie中，可供全部子域和页面使用
 * @param expires - cookie过期时间（天），默认1天
 * @returns 邀请人（用户编码）
 */
cacheInviter(expires?: number): string | undefined;
/**
 * 移除cookie中的邀请人缓存
 */
uncacheInviter(): void;
/**
 * 获取邀请人
 * @returns 邀请人（用户编码）
 */
getInviter(): string | undefined;

// 示例：
sdk.invite.getInviter();
```
### nftMarket模块
业务功能模块，封装了与nft市场交互的业务逻辑
```ts
/**
 *
 * @param payType - 支付类型枚举：enum PayType { ETH = 'ETH', Erc20 = 'Erc20', Currency = 'Currency' }
 * @param options - 支付选项：NftBuyOptions
 * ```ts
 * NftBuyOptions = NftBuyByETHOptions | NftBuyByErc20Options | NftBuyByCurrencyOptions
 * // 当payType为PayType.ETH时：
 * type NftBuyByETHOptions = {
 *     skuId: string;
 *     beforeSwitchChain?: (e: SwitchChainData) => Promise<void> | void; // 钩子函数 - 切换链之前；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     switchChainSuccess?: (e: SwitchChainData) => void;  // 钩子函数 - 切换链成功；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     switchChainFailed?: (e: Error & SwitchChainData) => void;  // 钩子函数 - 切换链失败；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     beforeOrder?: () => Promise<void> | void; // 钩子函数 - 创建订单前
 *     afterOrder?: (apiData: any) => Promise<void> | void; // 钩子函数 - 创建订单后
 *     beforeExchange?: () => Promise<void> | void; // 钩子函数 - 交易合约前
 * };
 * // 当payType为PayType.Erc20时：
 * type NftBuyByErc20Options = {
 *     skuId: string;
 *     beforeSwitchChain?: (e: SwitchChainData) => Promise<void> | void; // 钩子函数 - 切换链之前；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     switchChainSuccess?: (e: SwitchChainData) => void;  // 钩子函数 - 切换链成功；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     switchChainFailed?: (e: Error & SwitchChainData) => void;  // 钩子函数 - 切换链失败；SwitchChainData = { targetChainId: number, oldChainId: number }
 *     beforeOrder?: () => Promise<void> | void; // 钩子函数 - 创建订单前
 *     afterOrder?: (apiData: any) => Promise<void> | void; // 钩子函数 - 创建订单后
 *     beforeQueryBalance?: () => Promise<void> | void;  // 钩子函数 - 查询余额前
 *     afterQueryBalance?: (balance: string) => Promise<void> | void;  // 钩子函数 - 查询余额后
 *     beforeApprove?: () => Promise<void> | void; // 钩子函数 - Approval合约之前
 *     beforeExchange?: () => Promise<void> | void; // 钩子函数 - 交易合约前
 *     checkBalance?: boolean; // 默认为true，执行购买前优先检查erc余额
 * };
 * // 当payType为PayType.Currency时：
 * type NftBuyByCurrencyOptions = {
 *     skuId: string;
 *     payChannel: PayChannel; // enum PayChannel { Sendwyre = 2 }
 *     beforeOrder?: () => Promise<void> | void; // 钩子函数 - 创建订单前
 *     beforePay?: (order: any) => Promise<void> | void; // 钩子函数 - 支付前
 *     paySuccess?: () => Promise<void> | void; // 钩子函数 - 支付成功
 *     payCancel?: () => void; // 钩子函数 - 支付取消
 * };
 * ```
 * @returns Promise<void>，若异常会抛出相应的Error
 */
buyAndMint(payType: PayType, options: NftBuyOptions): Promise<void>;

// 示例：代币购买
await sdk.nftMarket.buyAndMint(PayType.Erc20, {
  skuId: "115"
});

// 示例：法币购买
await sdk.nftMarket.buyAndMint(PayType.Currency, {
  skuId: "115",
  payChannel: PayChannel.Sendwyre, // 或传入 2
});
```

## npm包列表
- @soundsright/types - 跨包的类型定义
- @soundsright/utils - 通用函数集合
- @soundsright/auth - auth模块，用于第三方授权和钱包授权
- @soundsright/chain - chain模块，用于链操作
- @soundsright/connector - connector模块，用于连接钱包
- @soundsright/contracts - contracts模块，合约api集合
- @soundsright/sdk - 功能统一集成的sdk
- @soundsright/service - service模块，用于服务器操作
- @soundsright/user - user模块，用于用户登录状态的操作
- @soundsright/share - share模块，用于分享