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

Add Sui Support #138

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 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
20 changes: 20 additions & 0 deletions docs/modules/pkh_sui.SuiWebAuth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Namespace: SuiWebAuth

[pkh-sui](pkh_sui.md).SuiWebAuth

## Functions

### getAuthMethod

▸ **getAuthMethod**(`suiProvider`, `account`): `Promise`<`AuthMethod`\>

#### Parameters

| Name | Type |
| :------ | :------ |
| `suiProvider` | `any` |
| `account` | `AccountId` |

#### Returns

`Promise`<`AuthMethod`\>
249 changes: 249 additions & 0 deletions docs/modules/pkh_sui.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
# Module: pkh-sui

## Sui AuthMethod and Verifier
Implements support to authenticate, authorize and verify with Sui accounts as a did:pkh with SIWE(X) and CACAO.
Primarly used with `did-session` and `@didtools/cacao`.

## Installation

```
npm install --save @didtools/pkh-solana
```

## Auth Usage

To Auth in web based env, use any injected Sui provider that implements the sui wallet standards interface with `SuiWebAuth`. see https://github.com/MystenLabs/sui/tree/main/sdk/wallet-adapter/wallet-standard and https://github.com/suiet/wallet-kit

```js
// Web Auth Usage
import { SuiWebAuth, getAccountIdByNetwork } from '@didtools/pkh-sui'
// ...

const suiProvider = // import/get your Solana provider (ie: window.phantom.solana)
const address = await suiProvider.connect().address
const accountId = getAccountIdByNetwork('mainnet', address.publicKey.toString())

const authMethod = await SuiWebAuth.getAuthMethod(suiProvider, accountId)
```

## Configuration

AuthMethod creators consume a standard Sui provider and an AccountId. AccountID follows the
CAIP10 standard. The helper methods `getAccountIdByNetwork` and `getAccountId` are provided, but you can also create an AccountID
using the CAIP library directly.

```js
import { AccountId } from 'caip'
import { getAccountIdByNetwork, getAccountId } from '@didtools/pkh-sui'

// Using network string
const accountId = getAccountIdByNetwork('mainnet', address)

// With CAIP
const suiMainnetChainId = 'mainnet'
const chainNameSpace = 'sui'
const chainId = `${chainNameSpace}:${ethMainnetChainId}`
const accountIdCAIP = new AccountId({ address, chainId })

// Using Solana Connection to query connect network/chain
const connection = new Connection(solanaWeb3.clusterApiUrl("mainnet-beta"))
const accountIdByConnection = await getAccountIdSolana(connection, address)

// accountId = accountIdCAIP = accountIdByConnection
```


## Verifier Usage

Verifiers are needed to verify different did:pkh signed payloads using CACAO. Libraries that need them will
consume a verifiers map allowing your to register the verifiers you want to support.

```js
import { Cacao } from '@didtools/cacao'
import { getSuiVerifier } from '@didtools/pkh-sui'
import { DID } from 'dids'

const verifiers = {
...getSuierifier()
}

// Directly with cacao
Cacao.verify(cacao, { verifiers, ...opts})

// With DIDS, reference DIDS for more details
const dids = //configured dids instance
await dids.verifyJWS(jws, { capability, verifiers, ...opts})
```

## Namespaces

- [SuiWebAuth](pkh_sui.SuiWebAuth.md)

## Type Aliases

### SupportedProvider

Ƭ **SupportedProvider**: `Object`

#### Type declaration

| Name | Type |
| :------ | :------ |
| `signMessage` | (`message`: `Uint8Array`, `type`: `string`) => `Promise`<{ `signature`: `Uint8Array` }\> |

## Variables

### CHAIN\_NAMESPACE

• `Const` **CHAIN\_NAMESPACE**: ``"sui"``

___

### SUI\_DEVNET\_CHAIN\_REF

• `Const` **SUI\_DEVNET\_CHAIN\_REF**: ``"devnet"``

___

### SUI\_TESTNET\_CHAIN\_REF

• `Const` **SUI\_TESTNET\_CHAIN\_REF**: ``"testnet"``

___

### SUI\_MAINNET\_CHAIN\_REF

• `Const` **SUI\_MAINNET\_CHAIN\_REF**: ``"mainnet"``

___

### VERSION

• `Const` **VERSION**: ``"1"``

___

### chainIdMap

• `Const` **chainIdMap**: `Object`

#### Type declaration

| Name | Type |
| :------ | :------ |
| `devnet` | `string` |
| `testnet` | `string` |
| `mainnet` | `string` |

## Functions

### assertSupportedConnection

▸ **assertSupportedConnection**(`suiProvider`): asserts suiProvider is SupportedProvider

#### Parameters

| Name | Type |
| :------ | :------ |
| `suiProvider` | `any` |

#### Returns

asserts suiProvider is SupportedProvider

___

### assertSupportedProvider

▸ **assertSupportedProvider**(`suiProvider`): asserts suiProvider is SupportedProvider

#### Parameters

| Name | Type |
| :------ | :------ |
| `suiProvider` | `any` |

#### Returns

asserts suiProvider is SupportedProvider

___

### getAccountId

▸ **getAccountId**(`suiProvider`, `address`): `Promise`<`AccountId`\>

#### Parameters

| Name | Type |
| :------ | :------ |
| `suiProvider` | `any` |
| `address` | `string` |

#### Returns

`Promise`<`AccountId`\>

___

### getAccountIdByNetwork

▸ **getAccountIdByNetwork**(`network`, `address`): `AccountId`

Helper function to get an accountId (CAIP10) for an Sui account by network string 'mainet' | 'testnet' | 'devenet'

#### Parameters

| Name | Type |
| :------ | :------ |
| `network` | `SuiNetwork` |
| `address` | `string` |

#### Returns

`AccountId`

___

### getSuiVerifier

▸ **getSuiVerifier**(): `Verifiers`

Get a configured CACAO SuiVerifier map for Sui accounts

#### Returns

`Verifiers`

___

### requestChainId

▸ **requestChainId**(`suiConnection`): `Promise`<`string`\>

#### Parameters

| Name | Type |
| :------ | :------ |
| `suiConnection` | `any` |

#### Returns

`Promise`<`string`\>

___

### verifySuiSignature

▸ **verifySuiSignature**(`cacao`, `options`): `void`

#### Parameters

| Name | Type |
| :------ | :------ |
| `cacao` | `Cacao` |
| `options` | `VerifyOptions` |

#### Returns

`void`
48 changes: 47 additions & 1 deletion packages/cacao/src/cacao.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Block from 'multiformats/block'
import { sha256 as hasher } from 'multiformats/hashes/sha2'
import { SiweMessage } from './siwx/siwe.js'
import { SiwsMessage } from './siwx/siws.js'
import { SiwSuiMessage } from './siwx/siwSui.js'
import { SiwTezosMessage } from './siwx/siwTezos.js'

// 5 minute default clockskew
Expand All @@ -24,7 +25,7 @@ export type Header = {
}

export type Signature = {
t: 'eip191' | 'eip1271' | 'solana:ed25519' | 'tezos:ed25519'
t: 'eip191' | 'eip1271' | 'solana:ed25519' | 'tezos:ed25519' | 'sui:ed25519'
s: string
}
export type Cacao = {
Expand Down Expand Up @@ -212,6 +213,51 @@ export namespace Cacao {
return cacao
}

export function fromSiwSuiMessage(siwSuiMessage: SiwSuiMessage): Cacao {
const cacao: Cacao = {
h: {
t: 'caip122',
},
p: {
domain: siwSuiMessage.domain,
iat: siwSuiMessage.issuedAt,
iss: `did:pkh:sui:${siwSuiMessage.chainId}:${siwSuiMessage.address}`,
aud: siwSuiMessage.uri,
version: siwSuiMessage.version,
nonce: siwSuiMessage.nonce,
},
}

if (siwSuiMessage.signature) {
cacao.s = {
t: 'sui:ed25519',
s: siwSuiMessage.signature,
}
}

if (siwSuiMessage.notBefore) {
cacao.p.nbf = siwSuiMessage.notBefore
}

if (siwSuiMessage.expirationTime) {
cacao.p.exp = siwSuiMessage.expirationTime
}

if (siwSuiMessage.statement) {
cacao.p.statement = siwSuiMessage.statement
}

if (siwSuiMessage.requestId) {
cacao.p.requestId = siwSuiMessage.requestId
}

if (siwSuiMessage.resources) {
cacao.p.resources = siwSuiMessage.resources
}

return cacao
}

export function fromSiwTezosMessage(siwTezosMessage: SiwTezosMessage): Cacao {
const cacao: Cacao = {
h: {
Expand Down
1 change: 1 addition & 0 deletions packages/cacao/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './siwx/siwe.js'
export * from './siwx/siws.js'
export * from './siwx/siwx.js'
export * from './siwx/siwSui.js'
export * from './siwx/siwTezos.js'
export * from './cacao.js'
25 changes: 25 additions & 0 deletions packages/cacao/src/siwx/siwSui.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SignatureType, SiwxMessage } from './siwx.js'


export class SiwSuiMessage extends SiwxMessage {
toMessage(): string {
return super.toMessage('Sui')
}

signMessage(): Uint8Array {
let message: Uint8Array
switch (this.type) {
case SignatureType.PERSONAL_SIGNATURE: {
message = new TextEncoder().encode(this.toMessage())
break
}

default: {
message = new TextEncoder().encode(this.toMessage())
break
}
}

return message
}
}
13 changes: 13 additions & 0 deletions packages/pkh-sui/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": ["3box", "3box/jest", "3box/typescript"],
"parserOptions": {
"project": ["tsconfig.lint.json"]
},
"rules": {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-ts-ignore": "off",
"@typescript-eslint/interface-name-prefix": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-unsafe-assignment": "off"
}
}
Loading