> ## Documentation Index
> Fetch the complete documentation index at: https://docs.magic.link/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Integrate with the Ethereum Blockchain using Flutter

## Installation

To interact with the Ethereum blockchain, Magic Flutter SDK embeds [`web3dart`](https://pub.dev/packages/web3dart) as sub dependency. No more extra dependency is needed.

## Initialization

The Magic class is the entry-point to the Magic SDK. It must be instantiated with a Magic **publishable** key.

```dart Dart icon="flutter" theme={null}
import 'package:magic_sdk/magic_sdk.dart';

void main() {
  runApp(const MyApp());

  Magic.instance = Magic("YOUR_PUBLISHABLE_KEY");
}
```

```dart Dart icon="flutter" theme={null}
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';
import 'package:web3dart/web3dart.dart';

class Web3Page extends StatefulWidget {
  const Web3Page({Key? key}) : super(key: key);

  @override
  State<Web3Page> createState() => _Web3PageState();
}

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final client = Web3Client.custom(Magic.instance.provider);
  final credential = MagicCredential(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    //Your page
  }
}
```

## Use Different Networks

### Testnet

Goerli Block Explorer: [https://goerli.etherscan.io](https://etherscan.io)

Goerli Testnet Faucet: [https://goerlifaucet.com](https://goerlifaucet.com)

```dart Dart icon="flutter" theme={null}
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/eth_network.dart';

void main() {
  runApp(const MyApp());

  Magic.instance = Magic.eth("YOUR_PUBLISHABLE_KEY", network: EthNetwork.goerli);
}
```

### Custom Node

You can allow specific URLs to interact with the Magic SDK, such as a custom RPC URL to send transactions to your node. The Content Security Policy (CSP) of a browser dictates what resources can be loaded. You can update the policy in the settings page of the dashboard with your custom URL.

<Note>
  **Note**

  The use of a custom node will require the RPC URL to the project's Content Security Policy from your [Magic Dashboard](https://dashboard.magic.link). Refer to the [CSP documentation](/embedded-wallets/wallets/security/content-security-policy).
</Note>

```dart Dart icon="flutter" theme={null}
import 'package:magic_sdk/magic_sdk.dart';

void main() {
  runApp(const MyApp());

  Magic.instance = Magic.custom("YOUR_PUBLISHABLE_KEY", rpcUrl: "https://your.own.node", chainId: 1011); // your own node
}
```

<Info>
  **Important**

  Do **not** set the custom nodes to local IP address (E.x. "[http://127.0.0.1"](http://127.0.0.1")). Local IP will point to the network environment inside the mobile device / simulator
</Info>

## Magic Credential

`web3dart` supports custodial design where the library will ask for user's private key to sign the payloads.

To integrate `web3dart` in non-custodial, We recommend you to use `MagicCredential` to optimize security.

```dart Dart icon="flutter" theme={null}
class MagicCredential {

  Future<EthereumAddress> getAccount()
  Future<String> personalSign({required Uint8List payload})
  Future<String> ethSign({required Uint8List payload})
  Future<String> signTypedDataLegacy({required Map payload})
  Future<String> signTypedData({required Map payload})
  Future<String> sendTransaction(Transaction transaction)
}
```

<Info>
  **Important**

  You will need to call `MagicCredential getAccount()` before other signing functions to get the public address that will be used from the current authenticated user.
</Info>

## Common Methods

### Send Transaction

```dart Dart icon="flutter" theme={null}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final credential = MagicCredential(Magic.instance.provider);
  final client = Web3Client.custom(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: [

              /// send Transaction
                ElevatedButton(
                  onPressed: () async {
                    var hash = await client.sendTransaction(
                      credential,
                      Transaction(
                        to: EthereumAddress.fromHex(
                            '0x01568bf1c1699bb9d58fac67f3a487b28ab4ab2d'),
                        gasPrice: EtherAmount.inWei(BigInt.two),
                        maxGas: 100000,
                        value: EtherAmount.fromUnitAndValue(EtherUnit.gwei, 2),
                      ),
                    );
                    debugPrint("transaction, $hash");
                  },
                  child: const Text('sendTransaction'),
                ),
            ])));
  }
}
```

### Sign Message

`Magic Credential` offers non-custodial signing apis

#### Eth Sign

```dart Dart icon="flutter" theme={null}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final credential = MagicCredential(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: [

              /// eth sign
              ElevatedButton(
                onPressed: () async {
                  List<int> list = utf8.encode("hello world");
                  Uint8List payload = Uint8List.fromList(list);
                  var signature = await credential.ethSign(payload: payload);
                  debugPrint(context, "eth_sign signature, $signature");
                },
                child: const Text('eth sign'),
              ),
            ])));
  }
}
```

#### Sign Typed Data Legacy (V1)

```dart Dart icon="flutter" theme={null}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final credential = MagicCredential(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: [

              /// Sign Typed Data V1
              ElevatedButton(
                onPressed: () async {
                  var payload = {
                    "type": "string",
                    "name": "Hello from Magic Labs",
                    "value": "This message will be assigned by you"
                  };
                  var signature = await credential.signTypedDataLegacy(payload: payload);
                  debugPrint(context, "sign Typed Data V1 signature, $signature");
                },
                child: const Text('sign Typed Data V1'),
              ),
            ])));
  }
}
```

#### Sign Typed Data (EIP 712)

```dart Dart icon="flutter" theme={null}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final credential = MagicCredential(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: [

              /// Sign Typed Data V3
              ElevatedButton(
                onPressed: () async {
                  var signature =
                  await credential.signTypedData(payload: signTypedDataV3Payload);
                  showResult(context, "sign Typed Data V3 signature, ${(signature)}");
                },
                child: const Text('sign Typed Data V3'),
              ),
            ])));
  }
}

var signTypedDataV3Payload = {
  "types": {
    "EIP712Domain": [
      {"name": "name", "type": "string"},
      {"name": "version", "type": "string"},
      {"name": "verifyingContract", "type": "address"}
    ],
    "Order": [
      {"name": "makerAddress", "type": "address"},
      {"name": "takerAddress", "type": "address"},
      {"name": "feeRecipientAddress", "type": "address"},
      {"name": "senderAddress", "type": "address"},
      {"name": "makerAssetAmount", "type": "uint256"},
      {"name": "takerAssetAmount", "type": "uint256"},
      {"name": "makerFee", "type": "uint256"},
      {"name": "takerFee", "type": "uint256"},
      {"name": "expirationTimeSeconds", "type": "uint256"},
      {"name": "salt", "type": "uint256"},
      {"name": "makerAssetData", "type": "bytes"},
      {"name": "takerAssetData", "type": "bytes"}
    ]
  },
  "domain": {
    "name": "0x Protocol",
    "version": "2",
    "verifyingContract": "0x35dd2932454449b14cee11a94d3674a936d5d7b2"
  },
  "message": {
    "exchangeAddress": "0x35dd2932454449b14cee11a94d3674a936d5d7b2",
    "senderAddress": "0x0000000000000000000000000000000000000000",
    "makerAddress": "0x338be8514c1397e8f3806054e088b2daf1071fcd",
    "takerAddress": "0x0000000000000000000000000000000000000000",
    "makerFee": "0",
    "takerFee": "0",
    "makerAssetAmount": "97500000000000",
    "takerAssetAmount": "15000000000000000",
    "makerAssetData":
    "0xf47261b0000000000000000000000000d0a1e359811322d97991e03f863a0c30c2cf029c",
    "takerAssetData":
    "0xf47261b00000000000000000000000006ff6c0ff1d68b964901f986d4c9fa3ac68346570",
    "salt": "1553722433685",
    "feeRecipientAddress": "0xa258b39954cef5cb142fd567a46cddb31a670124",
    "expirationTimeSeconds": "1553808833"
  },
  "primaryType": "Order"
};
```

### Get User Info

```dart Dart icon="flutter" theme={null}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:magic_sdk/magic_sdk.dart';
import 'package:magic_sdk/modules/web3/magic_credential.dart';

class _Web3PageState extends State<Web3Page> {
  final magic = Magic.instance;

  final credential = MagicCredential(Magic.instance.provider);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child:
            Column(mainAxisAlignment: MainAxisAlignment.center, children: [
              /// get account
              ElevatedButton(
                onPressed: () async {
                  var cred = await credential.getAccount();
                  debugPrint("account, ${cred.hex}");
                },
                child: const Text('getAccount'),
              ),
            ])));
  }
}
```

## Smart Contract

In this example, we'll be demonstrating how to use Magic with `web3dart` to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.

```solidity Solidity icon="ethereum" theme={null}
pragma solidity ^0.5.10;

contract HelloWorld {

  string public message;

  constructor(string memory initMessage) public {
    message = initMessage;
  }

  function update(string memory newMessage) public {
    message = newMessage;
  }
}
```

```dart Dart icon="flutter" theme={null}
class TestContract {
  static final deployedAddress =
  EthereumAddress.fromHex("0x8b211dfebf490a648f6de859dfbed61fa22f35e0");
  static const contractAbi =       '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
  static const byteCode =
      "0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032";
}
```

### Deploy Contract

```dart Dart icon="flutter" theme={null}
final credential = MagicCredential(Magic.instance.provider);
final client = Web3Client.custom(Magic.instance.provider);

var list = utf8.encode(TestContract.byteCode);
Uint8List payload = Uint8List.fromList(list);
final Transaction transaction = Transaction(
                to: null,
                from: credential.address,
                data: payload,
                maxGas: 2000000);
final String transactionId =
                await client.sendTransaction(credential, transaction);
```

### Read from Contract

```dart Dart icon="flutter" theme={null}
final credential = MagicCredential(Magic.instance.provider);
final client = Web3Client.custom(Magic.instance.provider);

final contract = DeployedContract(
    ContractAbi.fromJson(TestContract.contractAbi, ''),
    TestContract.deployedAddress);
final messageFunction = contract.function('message');
var message = await client.call(
contract: contract, function: messageFunction, params: []);
debugPrint("Contract Read Message, $message");
```

### Write to Contract

```dart Dart icon="flutter" theme={null}
final credential = MagicCredential(Magic.instance.provider);
final client = Web3Client.custom(Magic.instance.provider);

final contract = DeployedContract(
                ContractAbi.fromJson(TestContract.contractAbi, ''),
                TestContract.deployedAddress);
final updateFunction = contract.function('update');
var transactionId = await client.sendTransaction(
                credential,
                Transaction.callContract(
                    contract: contract,
                    function: updateFunction,
                    parameters: ["NEW_MESSAGE"]));
```

## Resources

* [Magic Flutter SDK](https://github.com/magiclabs/magic-flutter)
