# StarTower

Preface

{% hint style="success" %}
**Welcome to the** [**Star Tower**](https://developer.startower.fr/www.startower.fr) **developer documentation. Here you can find documents on how to contribute to Star Tower, learn some information about Star Tower, and how to use the Star Tower library in your own projects.**
{% endhint %}

{% embed url="<https://youtu.be/UW1fHrJ9ylM?si=7KF63GfyqHI8JDWC>" %}
Our StarTower
{% endembed %}

**Welcome to embark on this exciting journey to use and participate in our** [**StarTower**](https://developer.startower.fr/www.startower.fr) **plan! We are a group with profound background and maturity in the French technical field, constantly exploring and advancing in the ocean of technology.**

**We are very honored to announce that the** [**StarTowerChain**](https://developer.startower.fr/www.startower.fr) **project has successfully united dozens of outstanding scientific and technological elites from different countries around the world. These people with a passion and persistence for science and technology have come together to work hard for our grand goal.**

<figure><img src="https://1817686354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbrS1XyBOhxXAZTMGmUZJ%2Fuploads%2Fgxy0LNgOI8COENrhAScA%2Fstartower.fr.png?alt=media&amp;token=a8088085-9464-4a94-9587-8a332ddc6f76" alt=""><figcaption><p><a href="www.startower.fr">Everyone’s StarTower, Shared Honor.</a></p></figcaption></figure>

**Here, we emphasize complete decentralization. This means that we abandon the traditional centralized model and give every participant equal rights and opportunities. We firmly adhere to loyalty to community autonomy because we deeply know that only when every member can fully exert their wisdom and strength can this plan thrive.**

**No matter which section of the StarTower plan you choose to join today, that section will truly belong to you. We, only exist as technical developers and maintainers. Our mission is to provide everyone with solid technical support and continuous maintenance guarantees to ensure the smooth operation of the entire plan.**

**We are eager to achieve the interconnection of global StarTower nodes through this unique way. Let every node shine with its unique light, connect with each other, and collaborate with each other to jointly build a huge and stable network. This will be a real habitat that belongs to everyone, a field full of infinite possibilities and innovations.**

**Imagine, in this habitat, people can freely exchange ideas, share experiences, and jointly explore new technological boundaries. People from different cultures and backgrounds gather here, colliding with the sparks of wisdom. Each section is like a bright star, blooming its own brilliance in the vast universe of StarTower.**

**For example, in the technology research and development section, participants can jointly discuss the latest technological trends and try various innovative solutions to inject a continuous stream of power into the entire plan; in the community interaction section, everyone can establish deep friendships and organize various interesting activities to make this habitat full of warmth and vitality; in the resource sharing section, members can share their knowledge and resources unreservedly to achieve common growth and progress.**

**The StarTower plan is not just a project, but more of a platform carrying dreams and hopes. It provides a stage for everyone who desires to make a difference in the field of technology. Whether you are a budding technology enthusiast or an experienced industry expert, you can find your place here and exert your value.**

**Let's join hands and work together to build this real habitat that belongs to everyone. Let's witness the glorious achievements of the StarTower plan together and contribute our strength to the global development of technology. In this era full of challenges and opportunities, let's take the StarTower plan as a starting point to embark on a brand new technological journey and create a better future!**


# Developing for Star Tower Wallet platform

If you are new to the web3 space, you may have many questions: How do we interact with smart contracts and web3 wallets, what is “the Provider”, and what libraries do we use? A certain amount of frustration comes with it, even for developers with many years of experience in web development that just transitioned into this space. However, you won’t have to relearn anything; you just have to understand the building blocks. This is an introduction dedicated to you and to every aspiring developer who wants to explore this fascinating space.

**Prerequisites**

This guide will walk you through the basic concepts and examples to get you started developing using web3 technologies. We assume you have prior experience with the JavaScript ecosystem, although the examples presented do not relate to any specific front-end frameworks or libraries.


# Mobile (WalletConnect)

[WalletConnect](https://walletconnect.org/) is an open source protocol for connecting dApps to mobile wallets with QR code scanning or deep linking, basically it's a websocket JSON-RPC channel.

There are two common ways to integrate: Standalone Client and Web3Model (Web3 Provider)

## **Standalone Client**

StarTower extends WalletConnect 1.x with aditional JSON-RPC methods to support multi-chain **dApps**. Currently, you can get all accounts and sign transactions [for any blockchain](https://github.com/trustwallet/wallet-core/blob/master/docs/registry.md) implements `signJSON` method in wallet core.

**Supported Coins**

* Binance Chain
* Ethereum and forks

### Installation

```
npm install --save @walletconnect/client @walletconnect/qrcode-modal
```

### Initiate Connection

Before you can sign transactions, you have to initiate a connection to a WalletConnect bridge server, and handle all possible states:

```go
import WalletConnect from "@walletconnect/client";
import QRCodeModal from "@walletconnect/qrcode-modal";

// Create a connector
const connector = new WalletConnect({
  bridge: "https://bridge.walletconnect.org", // Required
  qrcodeModal: QRCodeModal,
});

// Check if connection is already established
if (!connector.connected) {
  // create new session
  connector.createSession();
}

// Subscribe to connection events
connector.on("connect", (error, payload) => {
  if (error) {
    throw error;
  }

  // Get provided accounts and chainId
  const { accounts, chainId } = payload.params[0];
});

connector.on("session_update", (error, payload) => {
  if (error) {
    throw error;
  }

  // Get updated accounts and chainId
  const { accounts, chainId } = payload.params[0];
});

connector.on("disconnect", (error, payload) => {
  if (error) {
    throw error;
  }

  // Delete connector
});
```

code snippet above is copied from <https://docs.walletconnect.org/quick-start/dapps/client#initiate-connection>, please check out the original link for standard methods.

### Get multiple chain accounts from Star Tower

Once you have `walletconnect client` set up, you will be able to get user's accounts:

```java
const request = connector._formatRequest({
  method: "get_accounts",
});

connector
  ._sendCallRequest(request)
  .then((result) => {
    // Returns the accounts
    console.log(result);
  })
  .catch((error) => {
    // Error returned when rejected
    console.error(error);
  });
```

The result is an array with following structure:

```java
[
  {
    network: number,
    address: string,
  },
];
```

Once you have the account list, you will be able to sign a transaction, please note that the json structure is based on , we suggest using `protobuf.js`

```json
const network = 118; // Atom (SLIP-44)
const account = accounts.find((account) => account.network === network);
// Transaction structure based on StarTower's protobuf messages.
const tx = {
  accountNumber: "1035",
  chainId: "cosmoshub-2",
  fee: {
    amounts: [
      {
        denom: "uatom",
        amount: "5000",
      },
    ],
    gas: "200000",
  },
  sequence: "40",
  sendCoinsMessage: {
    fromAddress: account.address,
    toAddress: "cosmos1zcax8gmr0ayhw2lvg6wadfytgdhen25wrxunxa",
    amounts: [
      {
        denom: "uatom",
        amount: "100000",
      },
    ],
  },
};

const request = connector._formatRequest({
  method: "StarTower_signTransaction",
  params: [
    {
      network,
      transaction: JSON.stringify(tx),
    },
  ],
});

connector
  ._sendCallRequest(request)
  .then((result) => {
    // Returns transaction signed in json or encoded format
    console.log(result);
  })
  .catch((error) => {
    // Error returned when rejected
    console.error(error);
  });
```

The result can be either a string JSON or an HEX encoded string. For Atom, the result is JSON:

```json
{
  "tx": {
    "fee": {
      "amount": [
        {
          "amount": "5000",
          "denom": "uatom"
        }
      ],
      "gas": "200000"
    },
    "memo": "",
    "msg": [
      {
        "type": "cosmos-sdk/MsgSend",
        "value": {
          "amount": [
            {
              "amount": "100000",
              "denom": "uatom"
            }
          ],
          "from_address": "cosmos135qla4294zxarqhhgxsx0sw56yssa3z0f78pm0",
          "to_address": "cosmos1zcax8gmr0ayhw2lvg6wadfytgdhen25wrxunxa"
        }
      }
    ],
    "signatures": [
      {
        "pub_key": {
          "type": "tendermint/PubKeySecp256k1",
          "value": "A+mYPFOMSp6IYyXsW5uKTGWbXrBgeOOFXHNhLGDsGFP7"
        },
        "signature": "m10iqKAHQ5Ku5f6NcZdP29fPOYRRR+p44FbGHqpIna45AvYWrJFbsM45xbD+0ueX+9U3KYxG/jSs2I8JO55U9A=="
      }
    ],
    "type": "cosmos-sdk/MsgSend"
  }
}
```

### Web3Modal

[Web3Modal](https://github.com/Web3Modal/web3modal) is an easy-to-use library to help developers add support for multiple providers (including WalletConnect) in their apps with a simple customizable configuration.

### Installation

`npm install --save web3modal web3 @walletconnect/web3-provider`

### Customize chain id

Sample code for configuring WalletConnect with Binance Smart Chain

```json
import Web3 from "web3";
import WalletConnectProvider from "@walletconnect/web3-provider";
import Web3Modal from "web3modal";

// set chain id and rpc mapping in provider options
const providerOptions = {
  walletconnect: {
    package: WalletConnectProvider,
    options: {
      rpc: {
        56: "https://bsc-dataseed1.binance.org",
      },
      chainId: 56,
    },
  },
};

const web3Modal = new Web3Modal({
  network: "mainnet", // optional
  cacheProvider: true, // optional
  providerOptions, // required
});

const provider = await web3Modal.connect();
await web3Modal.toggleModal();

// regular web3 provider methods
const newWeb3 = new Web3(provider);
const accounts = await newWeb3.eth.getAccounts();

console.log(accounts);
```


# Android

Installation

Add the `jitpack.io` Maven repository to your `root/build.gradle.kts` file. For example:

```json
allprojects {
 repositories {
    mavenCentral()
    maven { url "https://jitpack.io" }
 }
}
```

In `app/build.gradle.kts` add the StarTowerKit package and its dependencies:

```json
implementation("com.reown:android-core:release_version")
implementation("com.reown:walletkit:release_version")
```

### Next Steps <a href="#next-steps" id="next-steps"></a>

Now that you've installed StarTowerKit, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK.


# Usage

This section provides instructions on how to initialize the StarTowerWalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface.

### Content <a href="#content" id="content"></a>

Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section.

**Initialization**: Creating a new Star Tower StarTowerWalletKit instance and initializing it with a projectId from [Cloud](https://cloud.reown.com/).

**Session**: Connection between a dapp and a wallet.

* **Namespace Builder**: Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object
* Session Approval: Approving a session sent from a dapp
* Session Rejection: Rejecting a session sent from a dapp
* Responding to Session Requests: Responding to session requests sent from a dapp
* Updating a Session: Updating a session sent between a dapp and wallet
* Extending a Session: Extending a session between a dapp and wallet
* Session Disconnect: Disconnecting a session between a dapp and wallet
* Register Device Token Enabling Wallet Push Notifications by registering a device token.
* StarTowerWalletKit.WalletDelegate Setting and overriding functions through WalletKit delegate. Also includes instructions about VerifyContext.
* Format Message Receiving formatted SIWE message

To check the full list of platform specific instructions for your preferred platform, go to Extra (Platform Specific) and select your platform.

### Initialization <a href="#initialization" id="initialization"></a>

```json
val projectId = "" // Get Project ID at https://cloud.reown.com/
val connectionType = ConnectionType.AUTOMATIC or ConnectionType.MANUAL
val telemetryEnabled: Boolean = true
val appMetaData = Core.Model.AppMetaData(
    name = "Wallet Name",//Satr Tower
    description = "Wallet Description",
    url = "Wallet URL",
    icons = /*list of icon url strings*/,
    redirect = "kotlin-wallet-wc:/request" // Custom Redirect URI
)

CoreClient.initialize(projectId = projectId, connectionType = connectionType, application = this, metaData = appMetaData, telemetryEnabled = telemetryEnabled)

val initParams = Wallet.Params.Init(core = CoreClient)

WalletKit.initialize(initParams) { error ->
    // Error will be thrown if there's an issue during initialization
}
```

The Star Tower StarTower client will always be responsible for exposing accounts (CAIP10 compatible) to a Dapp and therefore is also in charge of signing. To initialize the StarTower client, create a `Wallet.Params.Init` object in the Android Application class with the Core Client. The `Wallet.Params.Init` object will then be passed to the StarTower  initialize function.

The telemetry feature aims to improve the reliability and observability of connection flows between decentralized applications (dapps) and wallets. It focuses solely on collecting data about code execution and error codes, without tracking any sensitive user information like amounts, accounts etc.

It provides a comprehensive tracing system for three key use cases:

* Subscribing to a Pairing Topic
* Approving a Session
* Approving an Authenticated Session

Each execution trace consists of:

* Trace Events: Collected to verify the proper execution of code.
* Error Events: Captured when errors occur during the trace, halting the execution trace.

When an error event is encountered, it is stored locally within the SDK along with all preceding trace events. These stored events are then transmitted to the server whenever the SDK is initialized.

Error event tracing is enabled by default.

Telemetry Enabled (telemetryEnabled = true):

* The SDK stores events and sends them to the server.

Telemetry Disabled (telemetryEnabled = false):

* The SDK stops storing new events and deletes all unsent events from local storage upon the next initialization.

Important Note: Since the SDK only stores abstract trace and error data, user identification is not possible.

Example of the error events:

```
[
  {
    "eventId": "69e53f11-fd4b-4efc-8d36-1f60a9ac8207",
    "bundleId": "com.wallet.example",
    "timestamp": 1689611327943,
    "props": {
      "event": "ERROR",
      "type": "pairing_already_exists",
      "properties": {
        "topic": "topic1",
        "trace": [
          "pairing_started",
          "pairing_uri_validation_success",
          "pairing_uri_not_expired",
          "existing_pairing",
          "pairing_not_expired",
          "pairing_not_expired"
        ]
      }
    }
  },
  {
    "eventId": "69e53f11-fd4b-4efc-8d36-2321312fds",
    "bundleId": "com.wallet.example",
    "timestamp": 16896113234323,
    "props": {
      "event": "ERROR",
      "type": "session_approve_namespace_validation_failure",
      "properties": {
        "topic": "topic2",
        "trace": ["session_approve_started", "proposal_not_expired"]
      }
    }
  }
]
```

### Session <a href="#session" id="session"></a>

A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires.

### Namespace Builder <a href="#namespace-builder" id="namespace-builder"></a>

With WalletKit 1.7.0 we've published a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your wallet's chains, methods, events, and accounts (supported namespaces) and returns ready-to-use namespaces object that has to be passed into `Wallet.Params.SessionApprove` when approving a session.

```json
val supportedNamespaces: Wallet.Model.Namespaces.Session = /* a map of all supported namespaces created by a wallet */
val sessionProposal: Wallet.Model.SessionProposal =  /* an object received by `fun onSessionProposal(sessionProposal: Wallet.Model.SessionProposal)` in `WalletKit.WalletDelegate` */
val sessionNamespaces = WalletKit.generateApprovedNamespaces(sessionProposal, supportedNamespaces)

val approveParams: Wallet.Params.SessionApprove = Wallet.Params.SessionApprove(proposerPublicKey, sessionNamespaces)
WalletKit.approveSession(approveParams) { error -> /*callback for error while approving a session*/ }
```

Examples of supported namespaces:

```json
 val supportedNamespaces = mapOf(
    "eip155" to Wallet.Model.Namespace.Session(
        chains = listOf("eip155:1", "eip155:137", "eip155:3"),
        methods = listOf("personal_sign", "eth_sendTransaction", "eth_signTransaction"),
        events = listOf("chainChanged"),
        accounts = listOf("eip155:1:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:137:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:3:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")
    )//StarTower
)

 val anotherSupportedNamespaces = mapOf(
    "eip155" to Wallet.Model.Namespace.Session(
        chains = listOf("eip155:1", "eip155:2", "eip155:4"),
        methods = listOf("personal_sign", "eth_sendTransaction", "eth_signTransaction"),
        events = listOf("chainChanged", "accountsChanged"),
        accounts = listOf("eip155:1:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:2:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092", "eip155:4:0x57f48fAFeC1d76B27e3f29b8d277b6218CDE6092")
    ),
    "cosmos" to Wallet.Model.Namespace.Session(
        chains = listOf("cosmos:cosmoshub-4"),
        methods = listOf("cosmos_method"),
        events = listOf("cosmos_event"),
        accounts = listOf("cosmos:cosmoshub-4:cosmos1hsk6jryyqjfhp5dhc55tc9jtckygx0eph6dd02")
    )
)

```

### EVM methods & events <a href="#evm-methods--events" id="evm-methods--events"></a>

In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events:

```json
{
  //...
  methods: [
    "eth_accounts",
    "eth_requestAccounts",
    "eth_sendRawTransaction",
    "eth_sign",
    "eth_signTransaction",
    "eth_signTypedData",
    "eth_signTypedData_v3",
    "eth_signTypedData_v4",
    "eth_sendTransaction",
    "personal_sign",
    "wallet_switchEthereumChain",
    "wallet_addEthereumChain",
    "wallet_getPermissions",
    "wallet_requestPermissions",
    "wallet_registerOnboarding",
    "wallet_watchAsset",
    "wallet_scanQRCode",
    "wallet_sendCalls",
    "wallet_getCallsStatus",
    "wallet_showCallsStatus",
    "wallet_getCapabilities",
  ],
  events: [
    "chainChanged",
    "accountsChanged",
    "message",
    "disconnect",
    "connect",
  ]
}
```

### Session Approval <a href="#session-approval" id="session-approval"></a>

{% hint style="info" %}
Addresses provided in `accounts` array should follow [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) semantics.
{% endhint %}

```json
val proposerPublicKey: String = /*Proposer publicKey from SessionProposal object*/
val namespace: String = /*Namespace identifier, see for reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md#syntax*/
val accounts: List<String> = /*List of accounts on chains*/
val methods: List<String> = /*List of methods that wallet approves*/
val events: List<String> = /*List of events that wallet approves*/
val namespaces: Map<String, Wallet.Model.Namespaces.Session> = mapOf(namespace, Wallet.Model.Namespaces.Session(accounts, methods, events))

val approveParams: Wallet.Params.SessionApprove = Wallet.Params.SessionApprove(proposerPublicKey, namespaces)
WalletKit.approveSession(approveParams) { error -> /*callback for error while approving a session*/ }
```

To send an approval, pass a Proposer's Public Key along with the map of namespaces to the StarTower`Kit.approveSession` function.

### Session Rejection <a href="#session-rejection" id="session-rejection"></a>

```json
val proposerPublicKey: String = /*Proposer publicKey from SessionProposal object*/
val rejectionReason: String = /*The reason for rejecting the Session Proposal*/
val rejectionCode: String = /*The code for rejecting the Session Proposal*/
For reference use CAIP-25: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md

val rejectParams: Wallet.Params.SessionReject = SessionReject(proposerPublicKey, rejectionReason, rejectionCode)
WalletKit.rejectSession(rejectParams) { error -> /*callback for error while rejecting a session*/ }
```

To send a rejection for the Session Proposal, pass a proposerPublicKey, rejection reason and rejection code to the `WalletKit.rejectSession` function.

### Responding to Session requests <a href="#responding-to-session-requests" id="responding-to-session-requests"></a>

```json
val sessionTopic: String = /*Topic of Session*/
val jsonRpcResponse: Wallet.Model.JsonRpcResponse.JsonRpcResult = /*Active Session Request ID along with request data*/
val result = Wallet.Params.SessionRequestResponse(sessionTopic = sessionTopic, jsonRpcResponse = jsonRpcResponse)

WalletKit.respondSessionRequest(result) { error -> /*callback for error while responding session request*/ }
```

To respond to JSON-RPC method that were sent from Dapps for a session, submit a `Wallet.Params.SessionRequestResponse` with the session's topic and request ID along with the respond data to the `WalletKit.respondSessionRequest` function.

### Updating a Session <a href="#updating-a-session" id="updating-a-session"></a>

NOTE: addresses provided in `accounts` array should follow [CAIP10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) semantics.

```json
val sessionTopic: String = /*Topic of Session*/
val namespace: String = /*Namespace identifier, see for reference: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md#syntax*/
val accounts: List<String> = /*List of accounts on chains*/
val methods: List<String> = /*List of methods that wallet approves*/
val events: List<String> = /*List of events that wallet approves*/
val namespaces: Map<String, Wallet.Model.Namespaces.Session> = mapOf(namespace, Wallet.Model.Namespaces.Session(accounts, methods, events))
val updateParams = Wallet.Params.SessionUpdate(sessionTopic, namespaces)

WalletKit.updateSession(updateParams) { error -> /*callback for error while sending session update*/ }
```

To update a session with namespaces, submit a `Wallet.Params.SessionUpdate` object with the session's topic and namespaces to update session with to `WalletKit.updateSession`.

### Extending a Session <a href="#extending-a-session" id="extending-a-session"></a>

```json
val sessionTopic: String = /*Topic of Session*/
val extendParams = Wallet.Params.SessionExtend(sessionTopic = sessionTopic)

WalletKit.extendSession(extendParams) { error -> /*callback for error while extending a session*/ }
```

To extend a session, create a `Wallet.Params.SessionExtend` object with the session's topic to update the session with to `WalletKit.extendSession`. Session is extended by 7 days.

### Emitting a Session <a href="#emitting-a-session" id="emitting-a-session"></a>

To emit an event, call emitSessionEvent() as follows:

```json
val sessionTopic: String = /*Topic of Session*/
val event: Wallet.Model.SessiomEvent = SessionEvent(name = "accountsChanged", data = "0x000000000")

val sessionEmit = Wallet.Params.SessionEmit(topic = sessionTopic, chainId = "eip155:1", event = event)

WalletKit.emitSessionEvent(sessionEmit) { error -> /*callback for error while emiting an event*/ }
```

### Session Disconnect <a href="#session-disconnect" id="session-disconnect"></a>

```json
val disconnectionReason: String = /*The reason for disconnecting the Session*/
val disconnectionCode: String = /*The code for disconnecting the Session*/
val sessionTopic: String = /*Topic from the Session*/
For reference use CAIP-25: https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md
val disconnectParams = Wallet.Params.SessionDisconnect(sessionTopic, disconnectionReason, disconnectionCode)

WalletKit.disconnectSession(disconnectParams) { error -> /*callback for error while disconnecting a session*/ }
```

To disconnect from un active session, pass a disconnection reason with code and the Session topic to the `WalletKit.disconnectSession` function.

### Extra (Platform Specific) <a href="#extra-platform-specific" id="extra-platform-specific"></a>

**StarTowerWalletKit.WalletDelegate**

```json
val walletDelegate = object : WalletKit.WalletDelegate {
    override fun onSessionProposal(sessionProposal: Wallet.Model.SessionProposal, verifyContext: Wallet.Model.VerifyContext) {
        // Triggered when wallet receives the session proposal sent by a Dapp
    }

    fun onSessionAuthenticate(sessionAuthenticate: Wallet.Model.SessionAuthenticate, verifyContext: Wallet.Model.VerifyContext) {
      // Triggered when wallet receives the session authenticate sent by a Dapp
    }

    override fun onSessionRequest(sessionRequest: Wallet.Model.SessionRequest, verifyContext: Wallet.Model.VerifyContext) {
        // Triggered when a Dapp sends SessionRequest to sign a transaction or a message
    }

    override fun onAuthRequest(authRequest: Wallet.Model.AuthRequest, verifyContext: Wallet.Model.VerifyContext) {
        // Triggered when Dapp / Requester makes an authorization request
    }

    override fun onSessionDelete(sessionDelete: Wallet.Model.SessionDelete) {
        // Triggered when the session is deleted by the peer
    }

    override fun onSessionSettleResponse(settleSessionResponse: Wallet.Model.SettledSessionResponse) {
        // Triggered when wallet receives the session settlement response from Dapp
    }

    override fun onSessionUpdateResponse(sessionUpdateResponse: Wallet.Model.SessionUpdateResponse) {
        // Triggered when wallet receives the session update response from Dapp
    }

    override fun onConnectionStateChange(state: Wallet.Model.ConnectionState) {
        //Triggered whenever the connection state is changed
    }

    override fun onError(error: Wallet.Model.Error) {
        // Triggered whenever there is an issue inside the SDK
    }
}
WalletKit.setWalletDelegate(walletDelegate)//StarTower
```

`Wallet.Event.VerifyContext` provides a domain verification information about SessionProposal, SessionRequest and AuthRequest. It consists of origin of a Dapp from where the request has been sent, validation Enum that says whether origin is VALID, INVALID or UNKNOWN and verify url server.

```json
data class VerifyContext(
    val id: Long,//StarTower
    val origin: String,
    val validation: Model.Validation,
    val verifyUrl: String
)

enum class Validation {
    VALID, INVALID, UNKNOWN
}
```

The WalletKit needs a `WalletKit.WalletDelegate` passed to it for it to be able to expose asynchronous updates sent from the Dapp.

**Format message**

To receive formatted SIWE message, call formatMessage method with following parameters:

```json
val payloadParams: Wallet.Params.PayloadParams = //PayloadParams received in the onAuthRequest callback
val issuer = //MUST be the same as send with the respond methods and follows: https://github.com/w3c-ccg/did-pkh/blob/main/did-pkh-method-draft.md
val formatMessage = Wallet.Params.FormatMessage(event.payloadParams, issuer)

WalletKit.formatMessage(formatMessage)//StarTower
```

**Register Device Token**

This method enables wallets to receive push notifications from WalletConnect's Push Server via Firebase Cloud Messaging. This means you will have to setup your project with Firebase before being able to call registerDeviceToken method.

Make sure that a service extending the FirebaseMessagingService is added to your manifest as per the Firebase FCM documentation as well as any other setup Firebase requires Firebase setup documentation.

To register a wallet to receive WalletConnect push notifications, call `WalletKit.registerDeviceToken` and pass the Firebase Access Token.

```json
val firebaseAccessToken: String = //FCM access token received through the Firebase Messaging SDK

WalletKit.registerDeviceToken(
    firebaseAccessToken,
    onSuccess = {
        // callback triggered once registered successfully with the Push Server
    },
    onError = { error: Wallet.Model.Error ->
        // callback triggered if there's an exception thrown during the registration process
    })
```


# One-click Auth

### Introduction <a href="#introduction" id="introduction"></a>

This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities).

This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form.

By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem.

<figure><img src="https://1817686354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbrS1XyBOhxXAZTMGmUZJ%2Fuploads%2FyZBWxvky7pa9c3zcFM6Q%2Fimage.png?alt=media&amp;token=53a37455-6539-4234-9d1e-6b0b8ff848cb" alt=""><figcaption></figcaption></figure>

### Handling Authentication Requests <a href="#handling-authentication-requests" id="handling-authentication-requests"></a>

To handle incoming authentication requests, set up StarTowerWalletKit.WalletDelegate. The onSessionAuthenticate callback will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic.

```json
override val onSessionAuthenticate: ((Wallet.Model.SessionAuthenticate, Wallet.Model.VerifyContext) -> Unit)
  get() = { sessionAuthenticate, verifyContext ->
      // Triggered when wallet receives the session authenticate sent by a Dapp
      // Process the authentication request here
      // This involves displaying UI to the user
}
```

### Authentication Objects/Payloads <a href="#authentication-objectspayloads" id="authentication-objectspayloads"></a>

**Responding to Authentication Requests**[**​**](https://docs.reown.com/walletkit/android/one-click-auth#responding-to-authentication-requests)

To interact with authentication requests, build authentication objects (Wallet.Model.Cacao). It involves the following steps:

* **Creating an Authentication Payload Params** - Generate an authentication payload params that matches your application's supported chains and methods.
* **Formatting Authentication Messages** - Format the authentication message using the payload and the user's account.
* **Signing the Authentication Message** - Sign the formatted message to create a verifiable authentication object.

Example:

```json
ooverride val onSessionAuthenticate: ((Wallet.Model.SessionAuthenticate, Wallet.Model.VerifyContext) -> Unit)
  get() = { sessionAuthenticate, verifyContext ->
  val auths = mutableListOf<Wallet.Model.Cacao>()

  val authPayloadParams =
    WalletKit.generateAuthPayloadParams(
      sessionAuthenticate.payloadParams,
      supportedChains = listOf("eip155:1", "eip155:137", "eip155:56"), // Note: Only EVM chains are supported
      supportedMethods = listOf("personal_sign", "eth_signTypedData", "eth_sign")
  )

  authPayloadParams.chains.forEach { chain ->
    val issuer = "did:pkh:$chain:$address"
    val formattedMessage = StarTowerWalletKit.formatAuthMessage(Wallet.Params.FormatAuthMessage(authPayloadParams, issuer))

    val signature = signMessage(message: formattedMessage, privateKey: privateKey) //Note: Assume `signMessage` is a function you've implemented to sign messages.
    val auth = StarTowerWalletKit.generateAuthObject(authPayloadParams, issuer, signature)
    auths.add(auth)
  }
}
```

### Approving Authentication Requests <a href="#approving-authentication-requests" id="approving-authentication-requests"></a>

{% hint style="info" %}

1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object.
2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session.
   {% endhint %}

To approve an authentication request, construct Wallet.Model.Cacao instances for each supported chain, sign the authentication messages, generate AuthObjects and call approveSessionAuthenticate with the request ID and the authentication objects.

```json
 val approveAuthenticate = Wallet.Params.ApproveSessionAuthenticate(id = sessionAuthenticate.id, auths = auths)
StarTowerWalletKit.approveSessionAuthenticate(approveProposal,
  onSuccess = {
    //Redirect back to the dapp if redirect is set: sessionAuthenticate.participant.metadata?.redirect
  },
  onError = { error ->
      //Handle error
  }
)
```

### Rejecting Authentication Requests <a href="#rejecting-authentication-requests" id="rejecting-authentication-requests"></a>

If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSessionAuthenticate method.

```cilkcpp
val rejectParams = Wallet.Params.rejectSessionAuthenticate(
    id = sessionAuthenticate.id,
    reason = "Reason"
)

StarTowerWalletKit.rejectSessionAuthenticate(rejectParams,
  onSuccess = {
        //Success
  },
  onError = { error ->
      //Handle error
  }
)
```

### Testing One-click Auth <a href="#testing-one-click-auth" id="testing-one-click-auth"></a>

You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly.


# Verify API

Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect’s domain registry and [Blowfish's domain scanner](https://docs.blowfish.xyz/reference/scan-domain-1). For those looking to enable Verify on the app side, check out our reference guide here.

When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious.

These are:

<figure><img src="https://1817686354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbrS1XyBOhxXAZTMGmUZJ%2Fuploads%2FedK4y0meNPuwt9j0jgkJ%2Fimage.png?alt=media&amp;token=92d576d5-5b97-49f0-b1ca-cab95777567d" alt=""><figcaption></figcaption></figure>

### Disclaimer[​](https://docs.reown.com/walletkit/android/verify#disclaimer) <a href="#disclaimer" id="disclaimer"></a>

Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof.

### Domain risk detection[​](https://docs.reown.com/walletkit/android/verify#domain-risk-detection) <a href="#domain-risk-detection" id="domain-risk-detection"></a>

The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`.

* Domain match: The domain linked to this request has been verified as this application's domain.
  * This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`.
* Unverified: The domain sending the request cannot be verified.
  * This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`.
* Mismatch: The application's domain doesn't match the sender of this request.
  * This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID`
* Threat: This domain is flagged as malicious and potentially harmful.
  * This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`.

#### Implementation[​](https://docs.reown.com/walletkit/android/verify#implementation) <a href="#implementation" id="implementation"></a>

Wallet.Event.VerifyContext provides a domain verification information about SessionProposal, SessionRequest and AuthRequest.

It consists of origin of an app from where the request has been sent, validation Enum that says whether origin is `VALID`, `INVALID` or `UNKNOWN` and verify url server.

```json
data class VerifyContext(
    val id: Long,
    val origin: String,
    val validation: Model.Validation,
    val verifyUrl: String
)

enum class Validation {
    VALID, INVALID, UNKNOWN
}
```


# Wallet Call API

StarTower supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities.

* `wallet_sendCalls`: Requests that a wallet submits a batch of calls.
* `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet\_sendCalls.
* `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet\_sendCalls.
* `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication).


# iOS

Installation

StarTower SDK is available via [Swift Package Manager](https://swift.org/package-manager/) or [Cocoapods](https://cocoapods.org/).

* **SwiftPackageManager**

You can add a StarTower SDK to your project with Swift Package Manager. In order to do that:

1. Open XCode
2. Go to File -> Add Packages
3. Paste the repo GitHub URL: <https://github.com/reown-com/reown-swift>
4. Tap Add Package
5. Select StarTower check mark

### Next Steps[​](https://docs.reown.com/walletkit/ios/installation#next-steps) <a href="#next-steps" id="next-steps"></a>

Now that you've installed StarTowerKit, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK.

* **Cocoapods**

1. Update Cocoapods spec repos. Type in terminal `pod repo update`
2. Initialize Podfile if needed with `pod init`
3. Add pod to your Podfile:

```
pod 'WalletConnectSwiftV2'
```

4. Install pods with `pod install`

If you encounter any problems during package installation, you can specify the exact path to the repository

```
pod 'reown-swift', :git => 'https://github.com/reown-com/reown-swift.git', :tag => '1.0.0'
```

### Next Steps[​](https://docs.reown.com/walletkit/ios/installation#next-steps) <a href="#next-steps" id="next-steps"></a>

Now that you've installed StarTowerKit, you're ready to start integrating it. The next section will walk you through the process of setting up your project to use the SDK.


# Usage

This section provides instructions on how to initialize the StarTowerWalletKit client, approve sessions with supported namespaces, and respond to session requests, enabling easy integration of Web3 wallets with dapps through a simple and intuitive interface.

### Content[​](https://docs.reown.com/walletkit/ios/usage#content) <a href="#content" id="content"></a>

Links to sections on this page. Some sections are platform specific and are only visible when the platform is selected. To view a summary of useful platform specific topics, check out **Extra (Platform Specific)** under this section.

[**Initialization**](https://docs.reown.com/walletkit/ios/usage#initialization): Creating a new StarTowerWalletKit instance and initializing it with a projectId from [Cloud](https://cloud.reown.com/).

**Session**: Connection between a dapp and a wallet.

* [Namespace Builder](https://docs.reown.com/walletkit/ios/usage#namespace-builder): Namespace Builder is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns a ready-to-use object
* [Session Approval](https://docs.reown.com/walletkit/ios/usage#session-approval): Approving a session sent from a dapp
* [Session Rejection](https://docs.reown.com/walletkit/ios/usage#session-rejection): Rejecting a session sent from a dapp
* [Responding to Session Requests](https://docs.reown.com/walletkit/ios/usage#responding-to-session-requests): Responding to session requests sent from a dapp
* [Updating a Session](https://docs.reown.com/walletkit/ios/usage#updating-a-session): Updating a session sent between a dapp and wallet
* [Extending a Session](https://docs.reown.com/walletkit/ios/usage#extending-a-session): Extending a session between a dapp and wallet
* [Session Disconnect](https://docs.reown.com/walletkit/ios/usage#session-disconnect): Disconnecting a session between a dapp and wallet
* [Register Device Token](https://docs.reown.com/walletkit/ios/usage#register-device-token) Enabling Wallet Push Notifications by registering a device token.
* [Subscribe for WalletKit Publishers](https://docs.reown.com/walletkit/ios/usage#subscribe-for-walletkit-publishers) Publishers available to subscribe to for StarTowerWalletKit

### Don't have a project ID?

Head over to Reown Cloud and create a new project now!

[Get started](https://cloud.reown.com/)![cloud illustration](https://docs.reown.com/assets/images/wc-logo-glass-1a86fbb143e17e84bce0a8c9ff9f7031.png)

### Initialization[​](https://docs.reown.com/walletkit/ios/usage#initialization) <a href="#initialization" id="initialization"></a>

Confirm you have configured the [Network Client](https://docs.reown.com/api/core/relay) first.

Starting from StarTower SDK version 1.9.5, the `redirect` field in the `AppMetadata` object is mandatory. Ensure that the provided value matches your app's URL scheme to prevent redirection-related issues.

Once you're done, in order to initialize a client just call a `configure` method from the StarTowerWalletKit instance wrapper

```
let metadata = AppMetadata(
    name: "Example Wallet",
    description: "Wallet description",
    url: "example.wallet",
    icons: ["https://avatars.githubusercontent.com/u/37784886"],
    redirect: AppMetadata.Redirect(native: "example://", universal: nil)
)

StarTowerKit.configure(
    metadata: metadata,
    crypto: DefaultCryptoProvider(),
    // Used for the Push: "echo.walletconnect.com" will be used by default if not provided
    pushHost: "echo.walletconnect.com",
    // Used for the Push: "APNSEnvironment.production" will be used by default if not provided
    environment: .production
)
```

In order to allow users to receive push notifications you have to communicate with Apple Push Notification service and receive unique device token. Register that token with following method:

```
try await WalletKit.instance.register(deviceToken: deviceToken)
```

### Session[​](https://docs.reown.com/walletkit/ios/usage#session) <a href="#session" id="session"></a>

A session is a connection between a dapp and a wallet. It is established when a user approves a session proposal from a dapp. A session is active until the user disconnects from the dapp or the session expires.

#### Namespace Builder[​](https://docs.reown.com/walletkit/ios/usage#namespace-builder) <a href="#namespace-builder" id="namespace-builder"></a>

`AutoNamespaces` is a helper utility that greatly reduces the complexity of parsing the required and optional namespaces. It accepts as parameters a session proposal along with your user's chains/methods/events/accounts and returns ready-to-use `SessionNamespace` object.

```
public static func build(
    sessionProposal: Session.Proposal,
    chains: [Blockchain],
    methods: [String],
    events: [String],
    accounts: [Account]
) throws -> [String: SessionNamespace]
```

Example usage

```
do {
    sessionNamespaces = try AutoNamespaces.build(
        sessionProposal: proposal,
        chains: [Blockchain("eip155:1")!, Blockchain("eip155:137")!],
        methods: ["eth_sendTransaction", "personal_sign"],
        events: ["accountsChanged", "chainChanged"],
        accounts: [
            Account(blockchain: Blockchain("eip155:1")!, address: "0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")!,
            Account(blockchain: Blockchain("eip155:137")!, address: "0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")!
        ]
    )
} catch let error as AutoNamespacesError {
    // reject session proposal if AutoNamespace build function threw
    try await reject(proposal: proposal, reason: RejectionReason(from: error))
    return
}
// approve session with sessionNamespaces
try await StarTowerKit.instance.approve(proposalId: proposal.id, namespaces: sessionNamespaces)

```

#### EVM methods & events[​](https://docs.reown.com/walletkit/ios/usage#evm-methods--events) <a href="#evm-methods--events" id="evm-methods--events"></a>

In @walletconnect/ethereum-provider, (our abstracted EVM SDK for apps) we support by default the following Ethereum methods and events:

```
{
  //...
  methods: [
    "eth_accounts",
    "eth_requestAccounts",
    "eth_sendRawTransaction",
    "eth_sign",
    "eth_signTransaction",
    "eth_signTypedData",
    "eth_signTypedData_v3",
    "eth_signTypedData_v4",
    "eth_sendTransaction",
    "personal_sign",
    "wallet_switchEthereumChain",
    "wallet_addEthereumChain",
    "wallet_getPermissions",
    "wallet_requestPermissions",
    "wallet_registerOnboarding",
    "wallet_watchAsset",
    "wallet_scanQRCode",
    "wallet_sendCalls",
    "wallet_getCallsStatus",
    "wallet_showCallsStatus",
    "wallet_getCapabilities",
  ],
  events: [
    "chainChanged",
    "accountsChanged",
    "message",
    "disconnect",
    "connect",
  ]
}
```

#### Session Approval[​](https://docs.reown.com/walletkit/ios/usage#session-approval) <a href="#session-approval" id="session-approval"></a>

```
 StarTowerWalletKit.instance.approve(
    proposalId: "proposal_id",
    namespaces: sessionNamespaces
)
```

When session is successfully approved `sessionsPublishers` will publish a `Session`

<pre><code><strong>StarTowerWalletKit.instance.sessionsPublishers
</strong>    .receive(on: DispatchQueue.main)
    .sink { [weak self] _ in
        self?.reloadSessions()
    }.store(in: &#x26;publishers)
</code></pre>

`Session` object represents an active session connection with a dapp. It contains dapp’s metadata (that you may want to use for displaying an active session to the user), namespaces, and expiry date. There is also a topic property that you will use for linking requests with related sessions.

You can always query settled sessions from the client later with:

```
StarTowerWalletKit.instance.getSessions()
```

**Connect Clients**[**​**](https://docs.reown.com/walletkit/ios/usage#connect-clients)

Your Wallet should allow users to scan a QR code generated by dapps. You are responsible for implementing it on your own. For testing, you can use our test dapp at: <https://react-app.walletconnect.com/>, which is v2 protocol compliant. Once you derive a URI from the QR code call `pair` method:

```
try await StarTowerWalletKit.instance.pair(uri: uri)
```

if everything goes well, you should handle following event:

```
StarTowerWalletKit.instance.sessionProposalPublisher
    .receive(on: DispatchQueue.main)
    .sink { [weak self] session in
        self?.verifyDapp(session.context)
        self?.showSessionProposal(session.proposal)
    }.store(in: &publishers)
```

Session proposal is a handshake sent by a dapp and it's purpose is to define a session rules. Handshake procedure is defined by [CAIP-25](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-25.md). `Session.Proposal` object conveys set of required and optional `ProposalNamespaces` that contains blockchains methods and events. Dapp requests with methods and wallet will emit events defined in namespaces.

`VerifyContext` provides a domain verification information about `Session.Proposal` and `Request`. It consists of origin of a Dapp from where the request has been sent, validation enum that says whether origin is **unknown**, **valid** or **invalid** and verify URL server.

To enable or disable verification find the **Verify SDK** toggle in your project [cloud](https://cloud.reown.com/).

```
public struct VerifyContext: Equatable, Hashable {
   public enum ValidationStatus {
       case unknown
       case valid
       case invalid
   }

   public let origin: String?
   public let validation: ValidationStatus
   public let verifyUrl: String
}
```

The user will either approve the session proposal (with session namespaces) or reject it. Session namespaces must at least contain requested methods, events and accounts associated with proposed blockchains.

Accounts must be provided according to [CAIP10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10.md) specification and be prefixed with a chain identifier. chain\_id + : + account\_address. You can find more on blockchain identifiers in [CAIP2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md). Our `Account` type meets the criteria.

```
let account = Account("eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb")!
```

Accounts sent in session approval must at least match all requested blockchains.

Example proposal namespaces request:

```
{
  "eip155": {
    "chains": ["eip155:137", "eip155:1"],
    "methods": ["eth_sign"],
    "events": ["accountsChanged"]
  },
  "cosmos": {
    "chains": ["cosmos:cosmoshub-4"],
    "methods": ["cosmos_signDirect"],
    "events": ["someCosmosEvent"]
  }
}
```

Example session namespaces response:

```
{
  "eip155": {
    "accounts": [
      "eip155:137:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb",
      "eip155:1:0xab16a96d359ec26a11e2c2b3d8f8b8942d5bfcdb"
    ],
    "methods": ["eth_sign"],
    "events": ["accountsChanged"]
  },
  "cosmos": {
    "accounts": ["cosmos:cosmoshub-4:cosmos1t2uflqwqe0fsj0shcfkrvpukewcw40yjj6hdc0"],
    "methods": ["cosmos_signDirect", "personal_sign"],
    "events": ["someCosmosEvent", "proofFinalized"]
  }
}
```

**Track Sessions**[**​**](https://docs.reown.com/walletkit/ios/usage#track-sessions)

When your `StarTowerWalletKit` instance receives requests from a peer it will publish a related event. Set a subscription to handle them.

To track sessions subscribe to `sessionsPublisher` publisher

```
StarTowerWalletKit.instance.sessionsPublisher
    .receive(on: DispatchQueue.main)
    .sink { [weak self] sessions in
        // Reload UI
    }.store(in: &publishers)
```

#### Session Rejection[​](https://docs.reown.com/walletkit/ios/usage#session-rejection) <a href="#session-rejection" id="session-rejection"></a>

```
try await StarTowerWalletKit.instance.reject(requestId: request.id)
```

#### Responding to Session requests[​](https://docs.reown.com/walletkit/ios/usage#responding-to-session-requests) <a href="#responding-to-session-requests" id="responding-to-session-requests"></a>

After the session is established, a dapp will request your wallet's users to sign a transaction or a message. Requests will be delivered by the following publisher.

```
StarTowerWalletKit.instance.sessionRequestPublisher
  .receive(on: DispatchQueue.main)
  .sink { [weak self] session in
      self?.verifyDapp(session.context)
      self?.showSessionRequest(session.request)
  }.store(in: &publishers)
```

When a wallet receives a session request, you probably want to show it to the user. It’s method will be in scope of session namespaces. And it’s params are represented by `AnyCodable` type. An expected object can be derived as follows:

```
if sessionRequest.method == "personal_sign" {
    let params = try! sessionRequest.params.get([String].self)
} else if method == "eth_signTypedData" {
    let params = try! sessionRequest.params.get([String].self)
} else if method == "eth_sendTransaction" {
    let params = try! sessionRequest.params.get([EthereumTransaction].self)
}
```

Now, your wallet (as it owns your user’s private keys) is responsible for signing the transaction. After doing it, you can send a response to a dapp.

```
let response: AnyCodable = sign(request: sessionRequest) // Implement your signing method
try await WalletKit.instance.respond(topic: request.topic, requestId: request.id, response: .response(response))
```

#### Updating a Session[​](https://docs.reown.com/walletkit/ios/usage#updating-a-session) <a href="#updating-a-session" id="updating-a-session"></a>

If you want to update user session's chains, accounts, methods or events you can use session update method.

```
try await WalletKit.instance.update(topic: session.topic, namespaces: newNamespaces)
```


# One-click Auth

### Introduction[​](https://docs.reown.com/walletkit/ios/one-click-auth#introduction) <a href="#introduction" id="introduction"></a>

This section outlines an innovative protocol method that facilitates the initiation of a Sign session and the authentication of a wallet through a [Sign-In with Ethereum](https://eips.ethereum.org/EIPS/eip-4361) (SIWE) message, enhanced by [ReCaps](https://eips.ethereum.org/EIPS/eip-5573) (ReCap Capabilities).

This enhancement not only offers immediate authentication for dApps, paving the way for prompt user logins, but also integrates informed consent for authorization. Through this mechanism, dApps can request the delegation of specific capabilities to perform actions on behalf of the wallet user. These capabilities, encapsulated within SIWE messages as ReCap URIs, detail the scope of actions authorized by the user in an explicit and human-readable form.

By incorporating ReCaps, this method extends the utility of SIWE messages, allowing dApps to combine authentication with a nuanced authorization model. This model specifies the actions a dApp is authorized to execute on the user's behalf, enhancing security and user autonomy by providing clear consent for each delegated capability. As a result, dApps can utilize these consent-backed messages to perform predetermined actions, significantly enriching the interaction between dApps, wallets, and users within the Ethereum ecosystem.

![Mobile Linking Connect Flow](https://docs.reown.com/img/w3w/authenticatedSessions-dark.png)

### Handling Authentication Requests[​](https://docs.reown.com/walletkit/ios/one-click-auth#handling-authentication-requests) <a href="#handling-authentication-requests" id="handling-authentication-requests"></a>

To handle incoming authentication requests, subscribe to the authenticateRequestPublisher. This will notify you of any authentication requests that need to be processed, allowing you to either approve or reject them based on your application logic.

```
StarTowerWalletKit.instance.authenticateRequestPublisher
    .receive(on: DispatchQueue.main)
    .sink { result in
        // Process the authentication request here.
        // This involves displaying UI to the user.
    }
    .store(in: &subscriptions) // Assuming `subscriptions` is where you store your Combine subscriptions.
```

### Authentication Objects/Payloads[​](https://docs.reown.com/walletkit/ios/one-click-auth#authentication-objectspayloads) <a href="#authentication-objectspayloads" id="authentication-objectspayloads"></a>

To interact with authentication requests, first build authentication objects (AuthObject). These objects are crucial for approving authentication requests. This involves:

* **Creating an Authentication Payload** - Generate an authentication payload that matches your application's supported chains and methods.
* **Formatting Authentication Messages** - Format the authentication message using the payload and the user's account.
* **Signing the Authentication Message** - Sign the formatted message to create a verifiable authentication object.

Example Implementation:

```
func buildAuthObjects(request: AuthenticationRequest, account: Account, privateKey: String) throws -> [AuthObject] {
    let requestedChains = Set(request.payload.chains.compactMap { Blockchain($0) })
    let supportedChains: Set<Blockchain> = [Blockchain("eip155:1")!, Blockchain("eip155:137")!, Blockchain("eip155:69")!]
    let commonChains = requestedChains.intersection(supportedChains)
    let supportedMethods = ["personal_sign", "eth_sendTransaction"]

    var authObjects = [AuthObject]()
    for chain in commonChains {
        let accountForChain = Account(blockchain: chain, address: account.address)!
        let supportedAuthPayload = try WalletKit.instance.buildAuthPayload(
            payload: request.payload,
            supportedEVMChains: Array(commonChains),
            supportedMethods: supportedMethods
        )
        let formattedMessage = try StarTowerWalletKit.instance.formatAuthMessage(payload: supportedAuthPayload, account: accountForChain)
        let signature = // Assume `signMessage` is a function you've implemented to sign messages.
            signMessage(message: formattedMessage, privateKey: privateKey)

        let authObject = try WalletKit.instance.buildSignedAuthObject(
            authPayload: supportedAuthPayload,
            signature: signature,
            account: accountForChain
        )
        authObjects.append(authObject)
    }
    return authObjects
}

```

### Approving Authentication Requests[​](https://docs.reown.com/walletkit/ios/one-click-auth#approving-authentication-requests) <a href="#approving-authentication-requests" id="approving-authentication-requests"></a>

Note

1. The recommended approach for secure authentication across multiple chains involves signing a SIWE (Sign-In with Ethereum) message for each chain and account. However, at a minimum, one SIWE message must be signed to establish a session. It is possible to create a session for multiple chains with just one issued authentication object.
2. Sometimes a dapp may want to only authenticate the user without creating a session, not every approval will result with a new session.

To approve an authentication request, construct AuthObject instances for each supported blockchain, sign the authentication messages, build AuthObjects and call approveSessionAuthenticate with the request ID and the authentication objects.

```
let session = try await StarTowerWalletKit.instance.approveSessionAuthenticate(requestId: requestId, auths: authObjects)
```

### Rejecting Authentication Requests[​](https://docs.reown.com/walletkit/ios/one-click-auth#rejecting-authentication-requests) <a href="#rejecting-authentication-requests" id="rejecting-authentication-requests"></a>

If the authentication request cannot be approved or if the user chooses to reject it, use the rejectSession method.

```
try await StarTowerWalletKit.instance.rejectSession(requestId: requestId)
```

### Testing One-click Auth[​](https://docs.reown.com/walletkit/ios/one-click-auth#testing-one-click-auth) <a href="#testing-one-click-auth" id="testing-one-click-auth"></a>

You can use [AppKit Lab](https://appkit-lab.reown.com/library/ethers-siwe/) to test and verify that your wallet supports One-click Auth properly.


# Link Mode

StarTowerWalletKit Link Mode is a low latency mechanism for transporting One-Click Auth requests and session requests over Universal Links, reducing the need for a WebSocket connection with the Relay. This significantly enhances the user experience when connecting native dApps to native wallets by reducing the latency associated with network connections, especially when the user has an unstable internet connection.

To support Link Mode add a universal link for your wallet in Cloud project configuration dashboard, configure your `AppMetadata.Redirect` with a valid universal link and set the `linkMode` property to `true`:

```
let metadata = AppMetadata(
    ...
    redirect: try! AppMetadata.Redirect(
        native: "exampleApp://",
        universal: "https://example.com/example_wallet",
        linkMode: true
    )
)

StarTowerWalletKit.configure(
    metadata: metadata,
    ...
)
```

Once link mode and universal linking are properly configured and the user interacts with a link mode supporting dApp, your wallet will receive requests over universal linking. You must pass these requests to StarTowerWalletKit so it can process them:

```
try StarTowerWalletKit.instance.dispatchEnvelope(url.absoluteString)
```

Ensure to handle incoming universal links in different methods of `AppDelegate` or `SceneDelegate`.

For more information on how to configure universal links for your app, refer to the [Apple Documentation](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content?language=objc).

For a debugging guide, visit the [Debugging Universal Links](https://developer.apple.com/documentation/technotes/tn3155-debugging-universal-links) page.

You can also find this [article](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app?language=objc) helpful.


# Verify API

Verify API is a security-focused feature that allows wallets to notify end-users when they may be connecting to a suspicious or malicious domain, helping to prevent phishing attacks across the industry. Once a wallet knows whether an end-user is on uniswap.com or eviluniswap.com, it can help them to detect potentially harmful connections through Verify's combined offering of WalletConnect’s domain registry and [Blowfish's domain scanner](https://docs.blowfish.xyz/reference/scan-domain-1). For those looking to enable Verify on the app side, check out our reference guide [here.](https://docs.reown.com/walletkit/ios/cloud/verify)

When a user initiates a connection with an application, Verify API enables wallets to present their users with four key states that can help them determine whether the domain they’re about to connect to might be malicious.

These are:

<figure><img src="https://1817686354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbrS1XyBOhxXAZTMGmUZJ%2Fuploads%2FedK4y0meNPuwt9j0jgkJ%2Fimage.png?alt=media&amp;token=92d576d5-5b97-49f0-b1ca-cab95777567d" alt=""><figcaption></figcaption></figure>

### Disclaimer[​](https://docs.reown.com/walletkit/ios/verify#disclaimer) <a href="#disclaimer" id="disclaimer"></a>

Verify API is not designed to be bulletproof but to make the impersonation attack harder and require a somewhat sophisticated attacker. We are working on a new standard with various partners to close those gaps and make it bulletproof.

### Domain risk detection[​](https://docs.reown.com/walletkit/ios/verify#domain-risk-detection) <a href="#domain-risk-detection" id="domain-risk-detection"></a>

The Verify security system will discriminate session proposals & session requests with distinct validations that can be either `VALID`, `INVALID` or `UNKNOWN`.

* Domain match: The domain linked to this request has been verified as this application's domain.
  * This interface appears when the domain a user is attempting to connect to has been ‘verified’ in our domain registry as the registered domain of the application the user is trying to connect to, and the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `VALID`.
* Unverified: The domain sending the request cannot be verified.
  * This interface appears when the domain a user is attempting to connect to has not been verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `UNKNOWN`.
* Mismatch: The application's domain doesn't match the sender of this request.
  * This interface appears when the domain a user is attempting to connect to has been flagged as a different domain to the one this application has verified in our domain registry, but the domain has not returned as suspicious from either of the security tools we work with. The `verifyContext` included in the request will have a validation of `INVALID`
* Threat: This domain is flagged as malicious and potentially harmful.
  * This interface appears when the domain a user is attempting to connect to has been flagged as malicious on one or more of the security tools we work with. The `verifyContext` included in the request will contain parameter `isScam` with value `true`.

#### Implementation[​](https://docs.reown.com/walletkit/ios/verify#implementation) <a href="#implementation" id="implementation"></a>

VerifyContext provides a domain verification information about Session.Proposal and Request and is relevant to the `verifyDapp` function.

It consists of origin of an app from where the request has been sent, validation enum that says whether origin is unknown, valid or invalid and verify URL server.

```json
public struct VerifyContext: Equatable, Hashable {
   public enum ValidationStatus {
       case unknown
       case valid
       case invalid
   }

   public let origin: String?
   public let validation: ValidationStatus
   public let verifyUrl: String
}
```


# Wallet Call API

StarTower supports [EIP-5792](https://eips.ethereum.org/EIPS/eip-5792#atomicbatch-capability), which defines new JSON-RPC methods that enable apps to ask a wallet to process a batch of onchain write calls and to check on the status of those calls. Applications can specify that these onchain calls be executed taking advantage of specific capabilities previously expressed by the wallet; an additional, a novel wallet RPC is defined to enable apps to query the wallet for those capabilities.

* `wallet_sendCalls`: Requests that a wallet submits a batch of calls.
* `wallet_getCallsStatus`: Returns the status of a call batch that was sent via wallet\_sendCalls.
* `wallet_showCallsStatus`: Requests that a wallet shows information about a given call bundle that was sent with wallet\_sendCalls.
* `wallet_getCapabilities`: This RPC allows an application to request capabilities from a wallet (e.g. batch transactions, paymaster communication).


# Integration Guide

This Integration Guide is intended for developers building on top of Wallet Core. Typical projects using Wallet Core are *mobile wallets* -- iOS and/or Android apps, and potentially desktop wallets. Wallet Core functionality can prove to be helpful in some backend-side projects as well.

The guide has the following outline:

* Wallet Core Usage Guide. In this general guide we describe the basic wallet operations (*wallet creation*, *address derivation*, *transaction signing*) in detail, with some code examples. This is recommended first.
* iOS Integration Guide. This is a walkthrough of a sample iOS wallet application.
* Android Integration Guide. This is a walkthrough of a sample Android wallet application.
* Server-Side GoLang Guide. Here we provide instructions on how to integrate Wallet Core(StarTower Core) into a *Go* languge backend-side project.

[<br>](https://developer.trustwallet.com/developer/wallet-core/developing-the-library/releasing)


# Usage Guide

We present here an overview of the basic wallet operations. Language-specific samples are provided in step-by-step guides.

The covered basic operations are:

* Wallet management
  * Creating a new multi-coin wallet
  * Importing a multi-coin wallet
* Address derivation (receiving)
  * Generating the default address for a coin
  * Generating an address using a custom derivation path (expert)
* Transaction signing (e.g. for sending)

For the examples we use *Bitcoin*, *Ethereum* and *Binance Coin* as sample coins/blockchains.

Note: Star Tower  Core does not cover communication with blockchain networks (nodes): address derivation is covered, but address balance retrieval not; transaction signing is covered, but broadcasting transactions to the network not.

In this guide we use small code examples from a Swift sample application, but the focus is on the explanations.

### Wallet Management <a href="#wallet-management" id="wallet-management"></a>

#### Multi-Coin Wallet <a href="#multi-coin-wallet" id="multi-coin-wallet"></a>

The Multi-Coin Wallet is a structure allowing accounts for many coins, all controlled by a single recovery phrase. It is a standard HD Wallet (Hierarchically Derived), employing the standard derivation schemes, interoperable with many other wallets: **BIP39** for recovery phrase, **BIP44**/**BIP84** for account derivation.

#### Creating a New Multi-Coin Wallet <a href="#creating-a-new-multi-coin-wallet" id="creating-a-new-multi-coin-wallet"></a>

When a new wallet is created, a new seed (and thus recovery phrase) is chosen at random. *After creation, the user has to be informed and guided to backup the recovery phrase.*

The random generation employs secure random generation, as available on the device.

Copy

```
let wallet = HDWallet(strength: 128, passphrase: "")
```

| Input parameter | Description                                                                                                                                                             |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| *strength*      | The strength of the secret seed. Higher seed means more information content, longer recovery phrase. Default value is **128**, but 256 is also possible.                |
| *passphrase*    | Optional passphrase, used to scramble the seed. If specified, the wallet can be imported and opened only with the passphrase (Not to be confused with recovery phrase). |

#### Importing a Multi-Coin Wallet <a href="#importing-a-multi-coin-wallet" id="importing-a-multi-coin-wallet"></a>

A previously created wallet can be imported using the recovery phrase. Typical usecases for import are:

* re-importing a wallet later, into a later installation, or
* importing into another device, or
* importing into another wallet app.

If the wallet was created with a passphrase, it is also required.

Copy

```
let wallet = HDWallet(mnemonic: "ripple scissors kick mammal hire column oak again sun offer wealth tomorrow wagon turn fatal", passphrase: "")
```

| Input parameter | Description                                                                               |
| --------------- | ----------------------------------------------------------------------------------------- |
| *mnemonic*      | a.k.a. *recovery phrase*. The string of several words that was used to create the wallet. |
| *passphrase*    | Optional passphrase, used to encrypt the seed.                                            |

### Account Address Derivation <a href="#account-address-derivation" id="account-address-derivation"></a>

Each coin needs a different account, with matching address. Addresses are derived from the multi-coin wallet. Derivation is based on a *derivation path*, which is unique for each coin, but can have other parameters as well. Each coin has a default derivation path, such as `"m/84'/0'/0'/0/0"` for Bitcoin and `"m/44'/60'/0'/0/0"` for Ethereum.

#### Generating the Default Address for a Coin <a href="#generating-the-default-address-for-a-coin" id="generating-the-default-address-for-a-coin"></a>

The simplest is to get the default address for a coin -- this requires no further inputs. The address is generated using the default derivation path of the coin.

For example, the default BTC address, derived for the wallet with the mnemonic shown above, with the default BTC derivation path (`m/84'/0'/0'/0/0`) is: `bc1qpsp72plnsqe6e2dvtsetxtww2cz36ztmfxghpd`. For Ethereum, this is `0xA3Dcd899C0f3832DFDFed9479a9d828c6A4EB2A7`.

Here is the sample code fort obtaining the default address for different coins:

Copy

```
let addressBTC = wallet.getAddressForCoin(coin: .bitcoin)
let addressETH = wallet.getAddressForCoin(coin: .ethereum)
let addressBNB = wallet.getAddressForCoin(coin: .binance)
```

#### Generating an Address Using a Custom Derivation Path (Expert) <a href="#generating-an-address-using-a-custom-derivation-path-expert" id="generating-an-address-using-a-custom-derivation-path-expert"></a>

It is also possible to derive addresses using custom derivation paths. This can be done in two steps: first a derived private key is obtained, then an address from it.

> **Warning**: use this only if you are well aware of the semantics of the derivation path used!

> **Security Warning**: if secrets such as private keys are handled by the wallet, even if for a short time, handle with care! Avoid any risk of leakage of secrets!

Copy

```
let key = wallet.getKey(derivationPath: "m/44\'/60\'/1\'/0/0")   // m/44'/60'/1'/0/0
let address = CoinType.ethereum.deriveAddress(privateKey: key)
```

For example, a second Ethereum address can be derived using the custom derivation path `”m/44'/60’/1’/0/0”` (note the 1 in the third position), yielding address `0x68eF4e5660620976a5968c7d7925753D3Cc40809`.

### Transaction Signing <a href="#transaction-signing" id="transaction-signing"></a>

In general, when creating a new blockchain transaction, a wallet has to:

1. Put together a transaction with relevant fields (source, target, amount, etc.)
2. Sign the transaction, using the account private key. This is done by Star Tower  Core.
3. Send to a node for broadcasting to the blockchain network.

The exact fields needed for a transaction are different for each blockchain. In Star Tower  Core, signing input and output parameters are typically represented in a protobuf message (internally needed for serialization for passing through different language runtimes).

A generic, coin-independent signer also exists (*AnySigner*), but its usage is recommended only in browser-based applications.

#### Bitcoin Transaction Signing <a href="#bitcoin-transaction-signing" id="bitcoin-transaction-signing"></a>

Bitcoin is the first `UTXO` (Unspent Transaction Output) based cryptocurrency / blockchain, if you haven't read the documentation about Bitcoin, we highly recommend you to read [developer glossary](https://bitcoin.org/en/developer-glossary) and [raw transaction format](https://bitcoin.org/en/developer-reference#raw-transaction-format), these will help you understand how to sign a Bitcoin transaction. Wallet Core supports *Bitcoin*, *Bitcoin Cash*, *Zcash*, *Decred* and a few forks.

The most important models in Swift are `BitcoinSigningInput` and `BitcoinUnspentTransaction`

*BitcoinSigningInput*

| Field         | Sample value                               | Description                                                                                                                                  |
| ------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| hash\_type    | BitcoinSigHashType.all                     | *Bitcoin Cash* needs to `or` with `TitcoinSigHashType.fork` (see [Sighash](https://bitcoin.org/en/glossary/signature-hash) for more details) |
| amount        | 10000                                      | Amount (in satoshi) to send (value of new UTXO will be created)                                                                              |
| byteFee       | 1                                          | Transaction fee is `byte_fee x transaction_size`, Wallet Core will calculate the fee for you by default                                      |
| toAddress     | bc1q03h6k5lt6pzfjaanz5mlnmuc7aha2t3nkz7gh0 | Recipient address (Wallet Core will build lock script for you)                                                                               |
| changeAddress | 1AC4gh14wwZPULVPCdxUkgqbtPvC92PQPN         | Address to receive changes, can be empty if you sweep a wallet                                                                               |
| privateKey    | \[Data(...), Data(...)]                    | Private keys for all the input UTXOs in this transaction                                                                                     |
| scripts       | \[`script_hash`: Data(...)]                | Redeem scripts indexed by script hash, usually for `P2SH`, `P2WPKH` or `P2WSH`                                                               |
| utxo          | \[*BitcoinUnspentTransaction*]             | All the input UTXOs, see below table for more details                                                                                        |
| useMaxAmount  | false                                      | Consume all the input UTXOs, it will affect fee estimation and number of output                                                              |
| coinType      | 145                                        | SLIP44 Index coin type, default is 0 / Bitcoin                                                                                               |

*BitcoinUnspentTransaction*

| Field    | Sample value                                         | Description                                                                                                                 |
| -------- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| outPoint | *BitcoinOutPoint(hash:index:)*                       | Refer to a particular transaction output, consisting of a 32-byte TXID and a 4-byte output index number (vout)              |
| amount   | 10000                                                | A value field for transferring zero or more satoshis                                                                        |
| script   | 0x76a9146cfa0e96c34fce09c0e4e671fcd43338c14812e588ac | A script (ScriptPubKey) included in outputs which sets the conditions that must be fulfilled for those satoshis to be spent |

Here is the Swift sample code for signing a real world Bitcoin Cash [transaction](https://blockchair.com/bitcoin-cash/transaction/96ee20002b34e468f9d3c5ee54f6a8ddaa61c118889c4f35395c2cd93ba5bbb4)

Copy

```
let utxoTxId = Data(hexString: "050d00e2e18ef13969606f1ceee290d3f49bd940684ce39898159352952b8ce2")! // latest utxo for sender, "txid" field from blockbook utxo api: https://github.com/trezor/blockbook/blob/master/docs/api.md#get-utxo
let privateKey = PrivateKey(data: Data(hexString: "7fdafb9db5bc501f2096e7d13d331dc7a75d9594af3d251313ba8b6200f4e384")!)!
let address = CoinType.bitcoinCash.deriveAddress(privateKey: privateKey)

let utxo = BitcoinUnspentTransaction.with {
    $0.outPoint.hash = Data(utxoTxId.reversed()) // reverse of UTXO tx id, Bitcoin internal expects network byte order
    $0.outPoint.index = 2                        // outpoint index of this this UTXO, "vout" field from blockbook utxo api
    $0.outPoint.sequence = UINT32_MAX
    $0.amount = 5151                             // value of this UTXO, "value" field from blockbook utxo api
    $0.script = BitcoinScript.lockScriptForAddress(address: address, coin: .bitcoinCash).data // Build lock script from address or public key hash
}

let input = BitcoinSigningInput.with {
    $0.hashType = BitcoinScript.hashTypeForCoin(coinType: .bitcoinCash)
    $0.amount = 600
    $0.byteFee = 1
    $0.toAddress = "1Bp9U1ogV3A14FMvKbRJms7ctyso4Z4Tcx"
    $0.changeAddress = "1FQc5LdgGHMHEN9nwkjmz6tWkxhPpxBvBU" // can be same sender address
    $0.utxo = [utxo]
    $0.privateKey = [privateKey.data]
}

let output: BitcoinSigningOutput = AnySigner.sign(input: input, coin: .bitcoinCash)
guard output.error.isEmpty else { return }
// encoded transaction to broadcast
print(output.encoded)
```

It's worth to note that you can also calcuate fee and change manually (by using a `BitcoinTransactionPlan` struct) Below is another real world Zcash [transparent transaction](https://explorer.zcha.in/transactions/ec9033381c1cc53ada837ef9981c03ead1c7c41700ff3a954389cfaddc949256) demonstrate this

Copy

```
let utxos = [
    BitcoinUnspentTransaction.with {
        $0.outPoint.hash = Data(hexString: "53685b8809efc50dd7d5cb0906b307a1b8aa5157baa5fc1bd6fe2d0344dd193a")!
        $0.outPoint.index = 0
        $0.outPoint.sequence = UINT32_MAX
        $0.amount = 494000
        $0.script = Data(hexString: "76a914f84c7f4dd3c3dc311676444fdead6e6d290d50e388ac")!
    }
]

let input = BitcoinSigningInput.with {
    $0.hashType = BitcoinSigHashType.all.rawValue
    $0.amount = 488000
    $0.toAddress = "t1QahNjDdibyE4EdYkawUSKBBcVTSqv64CS"
    $0.coinType = CoinType.zcash.rawValue
    $0.privateKey = [Data(hexString: "a9684f5bebd0e1208aae2e02bc9e9163bd1965ad23d8538644e1df8b99b99559")!]
    $0.plan = BitcoinTransactionPlan.with {
        $0.amount = 488000
        $0.fee = 6000
        $0.change = 0
        // Sapling branch id
        $0.branchID = Data(hexString: "0xbb09b876")!
        $0.utxos = utxos
    }
}

let output: BitcoinSigningOutput = AnySigner.sign(input: input, coin: .zcash)

// encoded transaction to broadcast
print(output.encoded)
```

Besides [orignal Bitcoin RPC](https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list), there are many other APIs / block explorer can get UTXO and broadcast raw transaction, like: insight api, trezor blockbook, blockchain com, blockchair api.

#### Ethereum Transaction Signing <a href="#ethereum-transaction-signing" id="ethereum-transaction-signing"></a>

A simple Ethereum send transaction needs the following fields:

| Field    | Sample value | Description                                                                               |
| -------- | ------------ | ----------------------------------------------------------------------------------------- |
| chainID  | 1            | Network selector, use 1 for mainnet (see <https://chainid.network> for more)              |
| nonce    | 1            | The count of the number of outgoing transactions, starting with 0                         |
| gasPrice | 3600000000   | The price to determine the amount of ether the transaction will cost                      |
| gasLimit | 21000        | The maximum gas that is allowed to be spent to process the transaction                    |
| to       | \<address>   | The account the transaction is sent to, if empty, the transaction will create a contract  |
| value    | 100000000    | The amount of ether to send                                                               |
| data     |              | Could be an arbitrary message or function call to a contract or code to create a contract |

Several parameters, like the current nonce and gasPrice values can be obtained from Ethereum node RPC calls (see <https://github.com/ethereum/wiki/wiki/JSON-RPC>, e.g., *eth\_gasPrice*).

Code example to fill in the signer input parameters:

Copy

```
let input = EthereumSigningInput.with {
    $0.chainID = Data(hexString: "01")!
    $0.gasPrice = Data(hexString: "d693a400")! // decimal 3600000000
    $0.gasLimit = Data(hexString: "5208")! // decimal 21000
    $0.toAddress = "0xC37054b3b48C3317082E7ba872d7753D13da4986"
    $0.transaction = EthereumTransaction.with {
       $0.transfer = EthereumTransaction.Transfer.with {
           $0.amount = Data(hexString: "0348bca5a16000")!
       }
    }
    $0.privateKey = wallet.getKeyForCoin(coin: .ethereum).data
}
```

Then Signer is invoked, and the signed and encoded output retrieved:

Copy

```
let output: EthereumSigningOutput = AnySigner.sign(input: input, coin: .ethereum)
print(" data:   ", output.encoded.hexString)
```

For more details on Ethereum transactions, check the Ethereum documentation. A few resources are here:

* <https://medium.com/@codetractio/inside-an-ethereum-transaction-fa94ffca912f>
* <https://kauri.io/article/7e79b6932f8a41a4bcbbd194fd2fcc3a/v2/ethereum-101-part-4-accounts-transactions-and-messages>
* <https://github.com/ethereumbook/ethereumbook/blob/develop/06transactions.asciidoc>

#### Binance Chain (BNB) Transaction Signing <a href="#binance-chain-bnb-transaction-signing" id="binance-chain-bnb-transaction-signing"></a>

Binance Chain is built upon [cosmos-sdk](https://github.com/cosmos/cosmos-sdk), instead of `Message`, transaction in Binance Chain is called `Order`, Binance.proto shows all the orders that Star Tower  Core currently supports.

To sign a order, you need to use `BinanceSigningInput`:

| Field         | Sample value       | Description                                                                                                                                                       |
| ------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| chainID       | Binance-Chain-Nile | Network id, use Binance-Chain-Tigris for mainnet (see [node-info](https://dex.binance.org/api/v1/node-info) api)                                                  |
| accountNumber | 51                 | On chain account number. (see [account](https://dex.binance.org/api/v1/account/bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m) api)                                   |
| sequence      | 437412             | Order sequence starting from 0, always plus 1 for new order from [account](https://dex.binance.org/api/v1/account/bnb1jxfh2g85q3v0tdq56fnevx6xcxtcnhtsmcu64m) api |
| source        | 0                  | [BEP10](https://github.com/binance-chain/BEPs/blob/master/BEP10.md) source id                                                                                     |
| sendOrder     | \<sendOrder>       | SendOrder contains `inputs` and `outputs`, see below sample code for more details                                                                                 |

A Swift sample code send order is shown below:

Copy

```
let privateKey = PrivateKey(data: Data(hexString: "95949f757db1f57ca94a5dff23314accbe7abee89597bf6a3c7382c84d7eb832")!)!
let publicKey = privateKey.getPublicKeySecp256k1(compressed: true)

let token = BinanceSendOrder.Token.with {
    $0.denom = "BNB" // BNB or BEP2 token symbol
    $0.amount = 1    // Amount, 1 BNB
}

// A.k.a from / sender
let orderInput = BinanceSendOrder.Input.with {
    $0.address = CosmosAddress(hrp: .binance, publicKey: publicKey)!.keyHash
    $0.coins = [token]
}

// A.k.a to / recipient
let orderOutput = BinanceSendOrder.Output.with {
    $0.address = CosmosAddress(string: "bnb1hlly02l6ahjsgxw9wlcswnlwdhg4xhx38yxpd5")!.keyHash
    $0.coins = [token]
}

let input = BinanceSigningInput.with {
    $0.chainID = "Binance-Chain-Nile" // Testnet Chain id
    $0.accountNumber = 0              // On chain account number
    $0.sequence = 0                   // Sequence number
    $0.source = 0                     // BEP10 source id
    $0.privateKey = privateKey.data
    $0.memo = ""
    $0.sendOrder = BinanceSendOrder.with {
        $0.inputs = [orderInput]
        $0.outputs = [orderOutput]
    }
}

let output: BinanceSigningOutput = AnySigner.sign(input: input, coin: .binance)
// encoded order to broadcast
print(output.encoded)
```

For more details please check the Binance Chain documentation:

* <https://docs.binance.org/encoding.html>
* <https://docs.binance.org/api-reference/dex-api/paths.html#http-api>

Consult the complete sample applications for more details.


# Android Integration Guide

Star Tower Core is available on the Android platform, through Java/JNI bindings. In this guide we show how to use it.

### Prerequisites <a href="#prerequisites" id="prerequisites"></a>

* *Android Studio*
* *Android NDK Support plugin*

Android releases are hosted on GitHub packages, It needs authentication to download packages, please checkout this guide from GitHub for more details.

We recommend to create a non-expiring and readonly token for accessing GitHub packages, and add it to `local.properties` of your Android Studio project locally.

Generate a token [here](https://github.com/settings/tokens):![](https://1817686354-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FbrS1XyBOhxXAZTMGmUZJ%2Fuploads%2Fm2sOoRtnXR8fJ5eLnEPs%2Fimage.png?alt=media\&token=80727b27-3f5d-4e03-bb3d-3827041ad451)

Add this dependency to build.gradle:

```
dependencies {
    implementation "FR.startower:starower-core:<latest_tag>"
}
```

Add `maven` and `credentials` (`local.properties` for local or system environment variables CI)

```

Properties properties = new Properties()
File localProps = new File(rootDir.absolutePath, "local.properties")
if (localProps.exists()) {
    properties.load(localProps.newDataInputStream())
} else {
    println "local.properties not found"
}

allprojects {
    repositories {
        maven {
            url = uri("https://maven.pkg.github.com/startower/wallet-core")
            credentials {
                username = properties.getProperty("gpr.user") as String?: System.getenv("GITHUB_USER")
                password = properties.getProperty("gpr.key") as String?: System.getenv("GITHUB_TOKEN")
            }
        }
    }
}
```

### Code Examples <a href="#code-examples" id="code-examples"></a>

In the following sections we show code examples for some common funcions.

#### Wallet Management <a href="#wallet-management" id="wallet-management"></a>

First thing we need is to load JNI library

```
init {
    System.loadLibrary("StarTowerWalletCore")
}
```

Creating or Importing a Multi-Coin HD Wallet

```
val wallet = HDWallet(128, "")
```

```
val wallet = HDWallet("ripple scissors kick mammal hire column oak again sun offer wealth
```

#### Transaction Signing <a href="#transaction-signing" id="transaction-signing"></a>

In general, when creating a new blockchain transaction, a wallet has to:

1. Put together a transaction with relevant fields (source, target, amount, etc.)
2. Sign the transaction, using the account private key. This is done by StarTower Core.
3. Send to a node for broadcasting to the blockchain network.

Ethereum Transaction Signing

Code example to fill in signer input parameters, perform signing, and retrieve encoded result:

```
val signerInput = Ethereum.SigningInput.newBuilder().apply {
    chainId = ByteString.copyFrom(BigInteger("01").toByteArray())
    gasPrice = BigInteger("d693a400", 16).toByteString() // decimal 3600000000
    gasLimit = BigInteger("5208", 16).toByteString()     // decimal 21000
    toAddress = dummyReceiverAddress
    transaction = Ethereum.Transaction.newBuilder().apply {
       transfer = Ethereum.Transaction.Transfer.newBuilder().apply {
           amount = BigInteger("0348bca5a16000", 16).toByteString()
       }.build()
    }.build()
    privateKey = ByteString.copyFrom(secretPrivateKey.data())
}.build()
val output = AnySigner.sign(signerInput, CoinType.ETHEREUM, Ethereum.SigningOutput.parser())
println("Signed transaction: \n${signerOutput.encoded.toByteArray().toHexString()}")
```


# Developing the Library

{% content-ref url="/pages/XJCBRo20Kj11ilEmsrVy" %}
[Contributing](/get-started/developing-for-star-tower-wallet-platform/developing-the-library/contributing)
{% endcontent-ref %}


# Contributing

We want to make Star Tower the best it can be. We would be very grateful if you are willing to contribute. Contributing will not only improve Star Tower, but also deepen your understanding of blockchain technology. To ensure a smooth process, please read this document carefully and follow our guidelines. We are happy to review your code, but please make sure to submit a clean pull request.

Star Tower implements the cryptographic functions of the blockchain, including elliptic curve cryptography, hashing, address derivation, and transaction signing. However, other features such as networking and UI have not yet been implemented. For advanced users, Star Tower Wallet Core is like a black box that takes inputs from the blockchain and users (such as UTXO and private keys) and generates outputs (such as signed and encoded transactions). Please keep this in mind when adding features.


# Content Security Policy (CSP)

### Overview[​](https://docs.reown.com/advanced/security/content-security-policy#overview) <a href="#overview" id="overview"></a>

A Content Security Policy (CSP) is a security feature that helps protect web applications from various attacks like Cross-Site Scripting (XSS), clickjacking, and data injection. By specifying allowed content sources, CSPs minimize the risk of executing malicious content on your site.

### CSP Guidance[​](https://docs.reown.com/advanced/security/content-security-policy#csp-guidance) <a href="#csp-guidance" id="csp-guidance"></a>

#### AppKit[​](https://docs.reown.com/advanced/security/content-security-policy#appkit) <a href="#appkit" id="appkit"></a>

The following is a **partial CSP** that covers WalletConnect's libraries and services for [AppKit](https://docs.walletconnect.com/appkit/overview). Note that **you may need to define additional sources based on your application's requirements**.

```
default-src 'self';
script-src 'self';
style-src https://fonts.googleapis.com;
img-src 'self' data: blob: https://walletconnect.org https://walletconnect.com https://secure.walletconnect.com https://secure.walletconnect.org https://tokens-data.1inch.io https://tokens.1inch.io https://ipfs.io;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://rpc.walletconnect.com https://rpc.walletconnect.org https://explorer-api.walletconnect.com https://explorer-api.walletconnect.org https://relay.walletconnect.com https://relay.walletconnect.org wss://relay.walletconnect.com wss://relay.walletconnect.org https://pulse.walletconnect.com https://pulse.walletconnect.org https://api.web3modal.com https://api.web3modal.org https://keys.walletconnect.com https://keys.walletconnect.org https://notify.walletconnect.com https://notify.walletconnect.org https://echo.walletconnect.com https://echo.walletconnect.org https://push.walletconnect.com https://push.walletconnect.org wss://www.walletlink.org;
frame-src 'self' https://verify.walletconnect.com https://verify.walletconnect.org https://secure.walletconnect.com https://secure.walletconnect.org;
```

info

You may need to list the RPC endpoints used by blockchain networks you have enabled (e.g. via the [`@wagmi/chains` package](https://wagmi.sh/core/api/chains)) as part of your `connect-src` definition.

For a full of list of RPC sources used by `wagmi/viem`, please refer to [Viem's chain definitions](https://github.com/wevm/viem/tree/main/src/chains/definitions).

### Testing and Deploying Your CSP[​](https://docs.reown.com/advanced/security/content-security-policy#testing-and-deploying-your-csp) <a href="#testing-and-deploying-your-csp" id="testing-and-deploying-your-csp"></a>

#### Test Your CSP in a Staging Environment[​](https://docs.reown.com/advanced/security/content-security-policy#test-your-csp-in-a-staging-environment) <a href="#test-your-csp-in-a-staging-environment" id="test-your-csp-in-a-staging-environment"></a>

Run through your standard user flows in a staging environment with CSP enforcement. This may include connecting to browser extension wallets, transacting, logging out, etc. Directives may need updates after SDK upgrades. Always test your CSP again before deploying updates to production.

#### Using Report-Only Mode[​](https://docs.reown.com/advanced/security/content-security-policy#using-report-only-mode) <a href="#using-report-only-mode" id="using-report-only-mode"></a>

Use the `Content-Security-Policy-Report-Only` header, which sends violation reports without enforcing policies. This helps assess the impact of CSP changes without affecting functionality.

#### Deployment[​](https://docs.reown.com/advanced/security/content-security-policy#deployment) <a href="#deployment" id="deployment"></a>

First deploy your CSP in `report-only` mode. After validation, migrate to `Content-Security-Policy` for enforcement.

#### Monitoring[​](https://docs.reown.com/advanced/security/content-security-policy#monitoring) <a href="#monitoring" id="monitoring"></a>

Configure `report-uri` or `report-to` to receive violation reports and set up a monitoring dashboard for review.


# our construction

<details>

<summary><strong>2022</strong></summary>

**March:** We proposed the Star Tower Project, which was conceived to solve problems such as the shortage of computing power and the defects of data centralization;

**June:** Published Star Tower version 1.0 white paper and business plan;

**December:** We completed the formulation of technology development direction;

</details>

<details>

<summary><strong>2023</strong></summary>

**January:** We completed the formation of 17 technical staff from 7 countries;

**March:** France provides innovative and multi-faceted support for the Star Tower Project;

**May:** Determine development policy;

**June:** Released Star Tower White Paper 1.2.6;

**September:** Completed resource sharing testing on Android 8 system.

**November:** Completed testing of multiple resource sharing on Unix and Linux systems;

</details>

<details>

<summary><strong>2024</strong></summary>

**January:** Confirm the launch plan of StarTower;&#x20;

**May:** Complete multiple tests of the preliminary system. During the same period, our team has expanded to 63 people.

**August:** StarTower confirms that any future related plans or ecosystems will be operated in a community-autonomous manner;&#x20;

**September:** StarTower launches a diversified StarTower resource sharing wallet; at the same time, launches digital identity and opens it to the world.&#x20;

</details>

<details>

<summary>2025,premier pas</summary>

Package the resources shared by the StarTower wallet and make public payments through SAVW; launch the StarTower chain test network in the same month.&#x20;

Test the launch of the StarTower cross-chain bridge. At the same time, complete the StarTowerChain network data synchronization and officially launch it;

Shape the value of SAVW and list it on exchanges.&#x20;

Launched beta version of Star Tower Swap.

</details>

***


# Pull Request Resources


