Repository: Dargon789/appkit
Pull request #160: Revert 4248 tomas/apkt 2695 bug extension wallet send flow resets confirm send view
Author: login: Dargon789
Created: 2025-04-21T05:03:43Z | Merged: 2025-04-21T05:10:50Z

# Description

Please include a brief summary of the change.

## Type of change

- [ ] Chore (non-breaking change that addresses non-functional tasks, maintenance, or code quality improvements)
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

# Associated Issues

For Linear issues: Closes APKT-xxx
For GH issues: closes #...

# Showcase (Optional)

If there is a UI change include the screenshots with before and after state.
If new feature is being introduced, include the link to demo recording.

# Checklist

- [ ] Code in this PR is covered by automated tests (Unit tests, E2E tests)
- [ ] My changes generate no new warnings
- [x] I have reviewed my own code
- [ ] I have filled out all required sections
- [x] I have tested my changes on the preview link
- [ ] Approver of this PR confirms that the changes are tested on the preview link

## Summary by Sourcery

Revert changes to the send token flow in the wallet, removing async/await handling and simplifying error management

Bug Fixes:
- Simplified error handling in token send methods across different blockchain namespaces

Enhancements:
- Removed loading state management from send token methods
- Simplified transaction sending logic in SendController

Tests:
- Removed some test cases related to loading state and send flow


Diff:
diff --git a/.changeset/nine-socks-make.md b/.changeset/nine-socks-make.md
deleted file mode 100644
index 7108aace95..0000000000
--- a/.changeset/nine-socks-make.md
+++ /dev/null
@@ -1,24 +0,0 @@
----
-'@reown/appkit-controllers': patch
-'@reown/appkit-scaffold-ui': patch
-'@reown/appkit-adapter-bitcoin': patch
-'@reown/appkit-adapter-ethers': patch
-'@reown/appkit-adapter-ethers5': patch
-'@reown/appkit-adapter-solana': patch
-'@reown/appkit-adapter-wagmi': patch
-'@reown/appkit': patch
-'@reown/appkit-utils': patch
-'@reown/appkit-cdn': patch
-'@reown/appkit-cli': patch
-'@reown/appkit-common': patch
-'@reown/appkit-core': patch
-'@reown/appkit-experimental': patch
-'@reown/appkit-polyfills': patch
-'@reown/appkit-siwe': patch
-'@reown/appkit-siwx': patch
-'@reown/appkit-ui': patch
-'@reown/appkit-wallet': patch
-'@reown/appkit-wallet-button': patch
----
-
-Fixes issue where sending an asset from a non-embedded wallet resulted in blank send view'
diff --git a/packages/controllers/src/controllers/SendController.ts b/packages/controllers/src/controllers/SendController.ts
index cb5038a3d3..50f73edc5b 100644
--- a/packages/controllers/src/controllers/SendController.ts
+++ b/packages/controllers/src/controllers/SendController.ts
@@ -109,27 +109,22 @@ export const SendController = {
     state.loading = loading
   },
 
-  async sendToken() {
-    try {
-      this.setLoading(true)
-      switch (ChainController.state.activeCaipNetwork?.chainNamespace) {
-        case 'eip155':
-          await this.sendEvmToken()
-
-          return
-        case 'solana':
-          await this.sendSolanaToken()
-
-          return
-        default:
-          throw new Error('Unsupported chain')
-      }
-    } finally {
-      this.setLoading(false)
+  sendToken() {
+    switch (ChainController.state.activeCaipNetwork?.chainNamespace) {
+      case 'eip155':
+        this.sendEvmToken()
+
+        return
+      case 'solana':
+        this.sendSolanaToken()
+
+        return
+      default:
+        throw new Error('Unsupported chain')
     }
   },
 
-  async sendEvmToken() {
+  sendEvmToken() {
     const activeChainNamespace = ChainController.state.activeChain as ChainNamespace
     const activeAccountType = AccountController.state.preferredAccountTypes?.[activeChainNamespace]
     if (this.state.token?.address && this.state.sendTokenAmount && this.state.receiverAddress) {
@@ -143,7 +138,7 @@ export const SendController = {
           network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
         }
       })
-      await this.sendERC20Token({
+      this.sendERC20Token({
         receiverAddress: this.state.receiverAddress,
         tokenAddress: this.state.token.address,
         sendTokenAmount: this.state.sendTokenAmount,
@@ -165,7 +160,7 @@ export const SendController = {
           network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
         }
       })
-      await this.sendNativeToken({
+      this.sendNativeToken({
         receiverAddress: this.state.receiverAddress,
         sendTokenAmount: this.state.sendTokenAmount,
         gasPrice: this.state.gasPrice,
@@ -264,7 +259,7 @@ export const SendController = {
   async sendNativeToken(params: TxParams) {
     const activeChainNamespace = ChainController.state.activeChain as ChainNamespace
     RouterController.pushTransactionStack({
-      view: null,
+      view: 'Account',
       goBack: false
     })
 
@@ -276,29 +271,49 @@ export const SendController = {
     )
     const data = '0x'
 
-    await ConnectionController.sendTransaction({
-      chainNamespace: 'eip155',
-      to,
-      address,
-      data,
-      value: value ?? BigInt(0),
-      gasPrice: params.gasPrice
-    })
-
-    EventsController.sendEvent({
-      type: 'track',
-      event: 'SEND_SUCCESS',
-      properties: {
-        isSmartAccount:
-          AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
-          W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
-        token: this.state.token?.symbol || '',
-        amount: params.sendTokenAmount,
-        network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
-      }
-    })
+    try {
+      await ConnectionController.sendTransaction({
+        chainNamespace: 'eip155',
+        to,
+        address,
+        data,
+        value: value ?? BigInt(0),
+        gasPrice: params.gasPrice
+      })
 
-    this.resetSend()
+      SnackController.showSuccess('Transaction started')
+      EventsController.sendEvent({
+        type: 'track',
+        event: 'SEND_SUCCESS',
+        properties: {
+          isSmartAccount:
+            AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
+            W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
+          token: this.state.token?.symbol || '',
+          amount: params.sendTokenAmount,
+          network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
+        }
+      })
+      this.resetSend()
+    } catch (error) {
+      // eslint-disable-next-line no-console
+      console.error('SendController:sendERC20Token - failed to send native token', error)
+      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
+      EventsController.sendEvent({
+        type: 'track',
+        event: 'SEND_ERROR',
+        properties: {
+          message: errorMessage,
+          isSmartAccount:
+            AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
+            W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
+          token: this.state.token?.symbol || '',
+          amount: params.sendTokenAmount,
+          network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
+        }
+      })
+      SnackController.showError('Something went wrong')
+    }
   },
 
   async sendERC20Token(params: ContractWriteParams) {
@@ -312,32 +327,55 @@ export const SendController = {
       Number(params.decimals)
     )
 
-    if (
-      AccountController.state.address &&
-      params.sendTokenAmount &&
-      params.receiverAddress &&
-      params.tokenAddress
-    ) {
-      const tokenAddress = CoreHelperUtil.getPlainAddress(
-        params.tokenAddress as CaipAddress
-      ) as `0x${string}`
-
-      await ConnectionController.writeContract({
-        fromAddress: AccountController.state.address as `0x${string}`,
-        tokenAddress,
-        args: [params.receiverAddress as `0x${string}`, amount ?? BigInt(0)],
-        method: 'transfer',
-        abi: ContractUtil.getERC20Abi(tokenAddress),
-        chainNamespace: 'eip155'
+    try {
+      if (
+        AccountController.state.address &&
+        params.sendTokenAmount &&
+        params.receiverAddress &&
+        params.tokenAddress
+      ) {
+        const tokenAddress = CoreHelperUtil.getPlainAddress(
+          params.tokenAddress as CaipAddress
+        ) as `0x${string}`
+
+        await ConnectionController.writeContract({
+          fromAddress: AccountController.state.address as `0x${string}`,
+          tokenAddress,
+          args: [params.receiverAddress as `0x${string}`, amount ?? BigInt(0)],
+          method: 'transfer',
+          abi: ContractUtil.getERC20Abi(tokenAddress),
+          chainNamespace: 'eip155'
+        })
+
+        SnackController.showSuccess('Transaction started')
+        this.resetSend()
+      }
+    } catch (error) {
+      // eslint-disable-next-line no-console
+      console.error('SendController:sendERC20Token - failed to send erc20 token', error)
+      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
+      EventsController.sendEvent({
+        type: 'track',
+        event: 'SEND_ERROR',
+        properties: {
+          message: errorMessage,
+          isSmartAccount:
+            AccountController.state.preferredAccountTypes?.eip155 ===
+            W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
+          token: this.state.token?.symbol || '',
+          amount: params.sendTokenAmount,
+          network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
+        }
       })
-
-      this.resetSend()
+      SnackController.showError('Something went wrong')
     }
   },
 
-  async sendSolanaToken() {
-    if (!this.state.sendTokenAmount) {
-      throw new Error('SendTokenAmount is required')
+  sendSolanaToken() {
+    if (!this.state.sendTokenAmount || !this.state.receiverAddress) {
+      SnackController.showError('Please enter a valid amount and receiver address')
+
+      return
     }
 
     RouterController.pushTransactionStack({
@@ -345,14 +383,20 @@ export const SendController = {
       goBack: false
     })
 
-    await ConnectionController.sendTransaction({
+    ConnectionController.sendTransaction({
       chainNamespace: 'solana',
       to: this.state.receiverAddress as `0x${string}`,
       value: this.state.sendTokenAmount
     })
-
-    this.resetSend()
-    AccountController.fetchTokenBalance()
+      .then(() => {
+        this.resetSend()
+        AccountController.fetchTokenBalance()
+      })
+      .catch(error => {
+        SnackController.showError('Failed to send transaction. Please try again.')
+        // eslint-disable-next-line no-console
+        console.error('SendController:sendToken - failed to send solana transaction', error)
+      })
   },
 
   resetSend() {
diff --git a/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts b/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts
index a96531493f..7665feb20e 100644
--- a/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts
+++ b/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts
@@ -1,22 +1,13 @@
 import { LitElement, html } from 'lit'
 import { state } from 'lit/decorators.js'
 
-import type { ChainNamespace } from '@reown/appkit-common'
-import {
-  AccountController,
-  ChainController,
-  EventsController,
-  RouterController,
-  SendController,
-  SnackController
-} from '@reown/appkit-controllers'
+import { ChainController, RouterController, SendController } from '@reown/appkit-controllers'
 import { UiHelperUtil, customElement } from '@reown/appkit-ui'
 import '@reown/appkit-ui/wui-button'
 import '@reown/appkit-ui/wui-flex'
 import '@reown/appkit-ui/wui-icon'
 import '@reown/appkit-ui/wui-preview-item'
 import '@reown/appkit-ui/wui-text'
-import { W3mFrameRpcConstants } from '@reown/appkit-wallet/utils'
 
 import '../../partials/w3m-wallet-send-details/index.js'
 import styles from './styles.js'
@@ -43,8 +34,6 @@ export class W3mWalletSendPreviewView extends LitElement {
 
   @state() private caipNetwork = ChainController.state.activeCaipNetwork
 
-  @state() private loading = SendController.state.loading
-
   public constructor() {
     super()
     this.unsubscribe.push(
@@ -56,7 +45,6 @@ export class W3mWalletSendPreviewView extends LitElement {
           this.gasPriceInUSD = val.gasPriceInUSD
           this.receiverProfileName = val.receiverProfileName
           this.receiverProfileImageUrl = val.receiverProfileImageUrl
-          this.loading = val.loading
         }),
         ChainController.subscribeKey('activeCaipNetwork', val => (this.caipNetwork = val))
       ]
@@ -132,7 +120,6 @@ export class W3mWalletSendPreviewView extends LitElement {
             @click=${this.onSendClick.bind(this)}
             size="lg"
             variant="main"
-            .loading=${this.loading}
           >
             Send
           </wui-button>
@@ -155,39 +142,8 @@ export class W3mWalletSendPreviewView extends LitElement {
     return null
   }
 
-  async onSendClick() {
-    if (!this.sendTokenAmount || !this.receiverAddress) {
-      SnackController.showError('Please enter a valid amount and receiver address')
-
-      return
-    }
-
-    try {
-      await SendController.sendToken()
-      SnackController.showSuccess('Transaction started')
-      RouterController.replace('Account')
-    } catch (error) {
-      SnackController.showError('Failed to send transaction. Please try again.')
-      // eslint-disable-next-line no-console
-      console.error('SendController:sendToken - failed to send transaction', error)
-
-      const activeChainNamespace = ChainController.state.activeChain as ChainNamespace
-
-      const errorMessage = error instanceof Error ? error.message : 'Unknown error'
-      EventsController.sendEvent({
-        type: 'track',
-        event: 'SEND_ERROR',
-        properties: {
-          message: errorMessage,
-          isSmartAccount:
-            AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
-            W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
-          token: this.token?.symbol || '',
-          amount: this.sendTokenAmount,
-          network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
-        }
-      })
-    }
+  onSendClick() {
+    SendController.sendToken()
   }
 
   private onCancelClick() {
diff --git a/packages/scaffold-ui/test/views/w3m-wallet-send-preview-view.test.ts b/packages/scaffold-ui/test/views/w3m-wallet-send-preview-view.test.ts
index fea7674de6..7d845d37f4 100644
--- a/packages/scaffold-ui/test/views/w3m-wallet-send-preview-view.test.ts
+++ b/packages/scaffold-ui/test/views/w3m-wallet-send-preview-view.test.ts
@@ -10,7 +10,6 @@ import {
   RouterController,
   SendController
 } from '@reown/appkit-controllers'
-import type { WuiButton } from '@reown/appkit-ui/wui-button'
 
 import { W3mWalletSendPreviewView } from '../../src/views/w3m-wallet-send-preview-view'
 
@@ -241,44 +240,4 @@ describe('W3mWalletSendPreviewView', () => {
     const valueText = element.shadowRoot?.querySelector('wui-text[variant="paragraph-400"]')
     expect(valueText?.textContent?.trim()).to.equal('$100.00')
   })
-
-  it('should redirect to account view when send is successful', async () => {
-    const sendSpy = vi.spyOn(SendController, 'sendToken').mockResolvedValue()
-    const routerSpy = vi.spyOn(RouterController, 'replace')
-    vi.spyOn(SendController, 'state', 'get').mockReturnValue({
-      ...mockSendControllerState
-    })
-
-    const element = await fixture<W3mWalletSendPreviewView>(
-      html`<w3m-wallet-send-preview-view></w3m-wallet-send-preview-view>`
-    )
-
-    await element.updateComplete
-
-    let button: WuiButton = element.shadowRoot?.querySelector('.sendButton') as WuiButton
-    button?.click()
-
-    await element.updateComplete
-
-    viExpect(sendSpy).toHaveBeenCalled()
-    viExpect(routerSpy).toHaveBeenCalledWith('Account')
-  })
-
-  it('should show loading state when sending', async () => {
-    // Mock SendController.state to have loading=true
-    vi.spyOn(SendController, 'state', 'get').mockReturnValue({
-      ...mockSendControllerState,
-      loading: true
-    })
-
-    const element = await fixture<W3mWalletSendPreviewView>(
-      html`<w3m-wallet-send-preview-view></w3m-wallet-send-preview-view>`
-    )
-
-    await element.updateComplete
-
-    // Get the button and check if it has the loading property set
-    const button = element.shadowRoot?.querySelector('.sendButton') as WuiButton
-    expect(button?.loading).to.equal(true)
-  })
 })


Reviews:
user: login: sourcery-ai[bot]
body: Hey @Dargon789 - I've reviewed your changes - here's some feedback:

**Overall Comments**:
- Consider adding try/catch blocks to `sendEvmToken` and `sendSolanaToken` to handle potential errors.
- The removal of `async` and try/finally block in `sendToken` might have unintended consequences; ensure that loading states are still handled correctly.

<details>
<summary>Here's what I looked at during the review</summary>

- 🟡 **General issues**: 1 issue found
- 🟢 **Security**: all looks good
- 🟢 **Testing**: all looks good
- 🟡 **Complexity**: 1 issue found
- 🟢 **Documentation**: all looks good
</details>

***

<details>
<summary>Sourcery is free for open source - if you like our reviews please consider sharing them ✨</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20got%20an%20instant%20code%20review%20from%20%40SourceryAI%2C%20and%20it%20was%20brilliant%21%20It%27s%20free%20for%20open%20source%20and%20has%20a%20free%20trial%20for%20private%20code.%20Check%20it%20out%20https%3A//sourcery.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://sourcery.ai)
- [Facebook](https://www.facebook.com/sharer/sharer.php?u=https://sourcery.ai)

</details>

<sub>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
</sub>
state: APPROVED
author_association: NONE
submitted_at: 2025-04-21T05:04:37Z

Review comments:
diff_hunk: @@ -276,29 +271,49 @@ export const SendController = {
     )
     const data = '0x'
 
-    await ConnectionController.sendTransaction({
-      chainNamespace: 'eip155',
-      to,
-      address,
-      data,
-      value: value ?? BigInt(0),
-      gasPrice: params.gasPrice
-    })
-
-    EventsController.sendEvent({
-      type: 'track',
-      event: 'SEND_SUCCESS',
-      properties: {
-        isSmartAccount:
-          AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
-          W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
-        token: this.state.token?.symbol || '',
-        amount: params.sendTokenAmount,
-        network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
-      }
-    })
+    try {
+      await ConnectionController.sendTransaction({
+        chainNamespace: 'eip155',
+        to,
+        address,
+        data,
+        value: value ?? BigInt(0),
+        gasPrice: params.gasPrice
+      })
 
-    this.resetSend()
+      SnackController.showSuccess('Transaction started')
+      EventsController.sendEvent({
+        type: 'track',
+        event: 'SEND_SUCCESS',
+        properties: {
+          isSmartAccount:
+            AccountController.state.preferredAccountTypes?.[activeChainNamespace] ===
+            W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,
+          token: this.state.token?.symbol || '',
path: packages/controllers/src/controllers/SendController.ts
user: login: sourcery-ai[bot]
body: **suggestion:** Inconsistent check for smart account type in error handling.

Within sendERC20Token's catch block, the code uses AccountController.state.preferredAccountTypes?.eip155 instead of dynamically accessing the active chain namespace (as in the try block). Using AccountController.state.preferredAccountTypes?.[activeChainNamespace] would maintain consistency across the code.

Suggested implementation:

```typescript
    isSmartAccount: AccountController.state.preferredAccountTypes?.[activeChainNamespace] === W3mFrameRpcConstants.ACCOUNT_TYPES.SMART_ACCOUNT,

```

Verify that the variable activeChainNamespace is correctly defined and in scope within the catch block. If not, ensure it is passed or defined appropriately to maintain consistency with the try block logic.
created_at: 2025-04-21T05:04:37Z
author_association: NONE
diff_hunk: @@ -109,27 +109,22 @@
     state.loading = loading
   },
 
-  async sendToken() {
-    try {
-      this.setLoading(true)
-      switch (ChainController.state.activeCaipNetwork?.chainNamespace) {
-        case 'eip155':
-          await this.sendEvmToken()
-
-          return
-        case 'solana':
-          await this.sendSolanaToken()
-
-          return
-        default:
-          throw new Error('Unsupported chain')
-      }
-    } finally {
-      this.setLoading(false)
+  sendToken() {
+    switch (ChainController.state.activeCaipNetwork?.chainNamespace) {
+      case 'eip155':
+        this.sendEvmToken()
+
+        return
+      case 'solana':
+        this.sendSolanaToken()
+
+        return
+      default:
+        throw new Error('Unsupported chain')
     }
   },
 
path: packages/controllers/src/controllers/SendController.ts
user: login: sourcery-ai[bot]
body: **issue (complexity):** Consider extracting the try/catch and notification logic into a helper function to reduce repetition and ensure consistent async/await usage across the send methods, including updating sendSolanaToken to use async/await for consistency .

Consider extracting the common try/catch and notification logic into a helper to reduce repetition and enforce a consistent async/await usage. For example, you could create a helper that wraps a transaction call and handles both the success and error notifications:

```ts
async function executeTransaction<T>(
  txFn: () => Promise<T>,
  successEvent: string,
  errorEvent: string,
  successMessage: string = 'Transaction started',
  errorMessage: string = 'Something went wrong'
): Promise<T> {
  try {
    const result = await txFn();
    SnackController.showSuccess(successMessage);
    EventsController.sendEvent({
      type: 'track',
      event: successEvent,
      properties: {
        token: this.state.token?.symbol || '',
        amount: this.state.sendTokenAmount,
        network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
      }
    });
    return result;
  } catch (error) {
    console.error(error);
    const message = error instanceof Error ? error.message : errorMessage;
    EventsController.sendEvent({
      type: 'track',
      event: errorEvent,
      properties: {
        message,
        token: this.state.token?.symbol || '',
        amount: this.state.sendTokenAmount,
        network: ChainController.state.activeCaipNetwork?.caipNetworkId || ''
      }
    });
    SnackController.showError(errorMessage);
    throw error;
  }
}
```

Then refactor your `sendNativeToken` and `sendERC20Token` methods like so:

```ts
async sendNativeToken(params: TxParams) {
  const activeChainNamespace = ChainController.state.activeChain as ChainNamespace;
  RouterController.pushTransactionStack({
    view: 'Account',
    goBack: false
  });
  const to = params.receiverAddress as `0x${string}`;
  const address = AccountController.state.address as `0x${string}`;
  const value = ConnectionController.parseUnits(
    params.sendTokenAmount.toString(),
    Number(params.decimals)
  );

  await executeTransaction(
    () =>
      ConnectionController.sendTransaction({
        chainNamespace: 'eip155',
        to,
        address,
        data: '0x',
        value: value ?? BigInt(0),
        gasPrice: params.gasPrice
      }),
    'SEND_SUCCESS',
    'SEND_ERROR'
  );
  this.resetSend();
}

async sendERC20Token(params: ContractWriteParams) {
  RouterController.pushTransactionStack({
    view: 'Account',
    goBack: false
  });
  const amount = ConnectionController.parseUnits(
    params.sendTokenAmount.toString(),
    Number(params.decimals)
  );

  await executeTransaction(
    () =>
      ConnectionController.writeContract({
        fromAddress: AccountController.state.address as `0x${string}`,
        tokenAddress: CoreHelperUtil.getPlainAddress(params.tokenAddress as CaipAddress) as `0x${string}`,
        args: [params.receiverAddress as `0x${string}`, amount ?? BigInt(0)],
        method: 'transfer',
        abi: ContractUtil.getERC20Abi(params.tokenAddress),
        chainNamespace: 'eip155'
      }),
    'SEND_SUCCESS',
    'SEND_ERROR'
  );
  this.resetSend();
}
```

Additionally, update `sendSolanaToken` to use async/await for consistency:

```ts
async sendSolanaToken() {
  if (!this.state.sendTokenAmount || !this.state.receiverAddress) {
    SnackController.showError('Please enter a valid amount and receiver address');
    return;
  }

  RouterController.pushTransactionStack({
    view: 'Account',
    goBack: false
  });

  try {
    await ConnectionController.sendTransaction({
      chainNamespace: 'solana',
      to: this.state.receiverAddress as `0x${string}`,
      value: this.state.sendTokenAmount
    });
    this.resetSend();
    AccountController.fetchTokenBalance();
  } catch (error) {
    SnackController.showError('Failed to send transaction. Please try again.');
    console.error('SendController:sendSolanaToken - failed to send solana transaction', error);
  }
}
```

This refactoring reduces duplication and keeps asynchronous patterns consistent without altering existing functionality.
created_at: 2025-04-21T05:04:37Z
author_association: NONE

PR comments:
user: login: codesandbox[bot]
created_at: 2025-04-21T05:03:46Z
body: #### Review or Edit in CodeSandbox

Open the branch in <a href="https://codesandbox.io/p/github/Dargon789/appkit/revert-4248-tomas/apkt-2695-bug-extension-wallet-send-flow-resets-confirm-send-view?mode=review&utm_source=gh_app">Web Editor</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=Dargon789&repo=appkit&branch=revert-4248-tomas/apkt-2695-bug-extension-wallet-send-flow-resets-confirm-send-view&utm_source=gh_app">VS Code</a> &bull; <a href="https://codesandbox.io/p/vscode?owner=Dargon789&repo=appkit&branch=revert-4248-tomas/apkt-2695-bug-extension-wallet-send-flow-resets-confirm-send-view&insiders=true&utm_source=gh_app">Insiders</a><br>
Open <a href="https://codesandbox.io/p/devtool/preview/Dargon789/appkit/revert-4248-tomas/apkt-2695-bug-extension-wallet-send-flow-resets-confirm-send-view?task=preview&port=51423&redirect=true&utm_source=gh_app">Preview</a>

<!-- open-in-codesandbox:complete -->

author_association: NONE
user: login: bolt-new-by-stackblitz[bot]
created_at: 2025-04-21T05:03:46Z
body: <a href="https://stackblitz.com/~/github.com/Dargon789/appkit/pull/160"><img src="https://developer.stackblitz.com/img/review_pr_small.svg" alt="Review PR in StackBlitz Codeflow" align="left" width="103" height="20"></a> _Run & review this pull request in [StackBlitz Codeflow](https://stackblitz.com/~/github.com/Dargon789/appkit/pull/160)._

author_association: NONE
user: login: sourcery-ai[bot]
created_at: 2025-04-21T05:03:47Z
body: <!-- Generated by sourcery-ai[bot]: start review_guide -->

## Reviewer's Guide by Sourcery

This pull request reverts changes related to the send flow, specifically addressing an issue where the confirm send view was being reset. The changes include refactoring the `sendToken` function, improving error handling, and removing associated tests and UI elements related to the loading state.

#### Sequence diagram for sendEvmToken

```mermaid
sequenceDiagram
  participant W3mWalletSendPreviewView
  participant SendController
  participant ChainController
  participant AccountController
  participant ConnectionController
  participant SnackController
  participant EventsController

  W3mWalletSendPreviewView->>SendController: onSendClick()
  SendController->>SendController: sendToken()
  SendController->>ChainController: activeCaipNetwork?.chainNamespace
  alt chainNamespace is 'eip155'
    SendController->>SendController: sendEvmToken()
    SendController->>AccountController: state.preferredAccountTypes
    SendController->>SendController: sendERC20Token()
    SendController->>CoreHelperUtil: getPlainAddress(tokenAddress)
    SendController->>ConnectionController: writeContract(params)
    activate ConnectionController
    ConnectionController-->>SendController: Success/Error
    deactivate ConnectionController
    alt Success
      SendController->>SnackController: showSuccess('Transaction started')
      SendController->>SendController: resetSend()
    else Error
      SendController->>EventsController: sendEvent(SEND_ERROR)
      SendController->>SnackController: showError('Something went wrong')
    end
  end
```

#### Sequence diagram for sendNativeToken

```mermaid
sequenceDiagram
  participant W3mWalletSendPreviewView
  participant SendController
  participant ChainController
  participant AccountController
  participant ConnectionController
  participant SnackController
  participant EventsController
  participant RouterController

  W3mWalletSendPreviewView->>SendController: onSendClick()
  SendController->>SendController: sendToken()
  SendController->>ChainController: activeCaipNetwork?.chainNamespace
  alt chainNamespace is 'eip155'
    SendController->>SendController: sendEvmToken()
    SendController->>AccountController: state.preferredAccountTypes
    SendController->>SendController: sendNativeToken(params)
    SendController->>RouterController: pushTransactionStack({view: 'Account', goBack: false})
    SendController->>ConnectionController: sendTransaction(params)
    activate ConnectionController
    ConnectionController-->>SendController: Success/Error
    deactivate ConnectionController
    alt Success
      SendController->>SnackController: showSuccess('Transaction started')
      SendController->>EventsController: sendEvent(SEND_SUCCESS)
      SendController->>SendController: resetSend()
    else Error
      SendController->>EventsController: sendEvent(SEND_ERROR)
      SendController->>SnackController: showError('Something went wrong')
    end
  end
```

### File-Level Changes

| Change | Details | Files |
| ------ | ------- | ----- |
| Refactors the `sendToken` function in `SendController` to remove the `try...finally` block and `setLoading` calls, streamlining the token sending process. | <ul><li>Removes the `try...finally` block from `sendToken`.</li><li>Removes `this.setLoading(true)` at the beginning of the `sendToken` function.</li><li>Removes `this.setLoading(false)` in the `finally` block of the `sendToken` function.</li></ul> | `packages/controllers/src/controllers/SendController.ts` |
| Makes `sendEvmToken` and `sendNativeToken` synchronous and handles transaction sending and error display within `sendNativeToken` using `try...catch`. | <ul><li>Removes the `async` keyword from the `sendEvmToken` function.</li><li>Removes the `async` keyword from the `sendNativeToken` function.</li><li>Adds a `try...catch` block in `sendNativeToken` to handle transaction sending and error display.</li><li>Displays a success message using `SnackController.showSuccess` after a successful transaction in `sendNativeToken`.</li><li>Displays an error message using `SnackController.showError` if sending the transaction fails in `sendNativeToken`.</li><li>Adds error logging using `console.error` in the catch block of `sendNativeToken`.</li><li>Adds event tracking for send errors in `sendNativeToken`.</li></ul> | `packages/controllers/src/controllers/SendController.ts` |
| Improves error handling and feedback for `sendERC20Token` by wrapping the transaction logic in a `try...catch` block and displaying appropriate snackbar messages. | <ul><li>Wraps the ERC20 token sending logic in a `try...catch` block.</li><li>Displays a success message using `SnackController.showSuccess` after a successful transaction.</li><li>Displays an error message using `SnackController.showError` if sending the transaction fails.</li><li>Adds error logging using `console.error` in the catch block.</li><li>Adds event tracking for send errors.</li></ul> | `packages/controllers/src/controllers/SendController.ts` |
| Adds error handling and feedback to `sendSolanaToken` using promises and snackbar messages. | <ul><li>Adds a check for valid amount and receiver address, displaying an error message if either is missing.</li><li>Uses promises to handle the asynchronous `sendTransaction` call.</li><li>Displays a success message and resets the send state on successful transaction.</li><li>Displays an error message if the transaction fails.</li><li>Adds error logging using `console.error` in the catch block.</li></ul> | `packages/controllers/src/controllers/SendController.ts` |
| Removes tests related to redirection and loading state in `W3mWalletSendPreviewView`. | <ul><li>Removes the test case for redirection to the account view on successful send.</li><li>Removes the test case for showing the loading state during sending.</li></ul> | `packages/scaffold-ui/test/views/w3m-wallet-send-preview-view.test.ts` |
| Removes the loading state and updates the `onSendClick` method in `W3mWalletSendPreviewView` to directly call `SendController.sendToken` without awaiting or handling the result. | <ul><li>Removes the `@state() private loading` property.</li><li>Removes `this.loading = val.loading` from the subscription.</li><li>Removes the `.loading=${this.loading}` property from the `wui-button` element.</li><li>Updates the `onSendClick` method to directly call `SendController.sendToken`.</li><li>Removes the `try...catch` block from the `onSendClick` method.</li><li>Removes the `RouterController.replace('Account')` call from the `onSendClick` method.</li></ul> | `packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts` |
| Removes the changeset file. | <ul><li>Removes the `.changeset/nine-socks-make.md` file.</li></ul> | `.changeset/nine-socks-make.md` |

---

<details>
<summary>Tips and commands</summary>

#### Interacting with Sourcery

- **Trigger a new review:** Comment `@sourcery-ai review` on the pull request.
- **Continue discussions:** Reply directly to Sourcery's review comments.
- **Generate a GitHub issue from a review comment:** Ask Sourcery to create an
  issue from a review comment by replying to it. You can also reply to a
  review comment with `@sourcery-ai issue` to create an issue from it.
- **Generate a pull request title:** Write `@sourcery-ai` anywhere in the pull
  request title to generate a title at any time. You can also comment
  `@sourcery-ai title` on the pull request to (re-)generate the title at any time.
- **Generate a pull request summary:** Write `@sourcery-ai summary` anywhere in
  the pull request body to generate a PR summary at any time exactly where you
  want it. You can also comment `@sourcery-ai summary` on the pull request to
  (re-)generate the summary at any time.
- **Generate reviewer's guide:** Comment `@sourcery-ai guide` on the pull
  request to (re-)generate the reviewer's guide at any time.
- **Resolve all Sourcery comments:** Comment `@sourcery-ai resolve` on the
  pull request to resolve all Sourcery comments. Useful if you've already
  addressed all the comments and don't want to see them anymore.
- **Dismiss all Sourcery reviews:** Comment `@sourcery-ai dismiss` on the pull
  request to dismiss all existing Sourcery reviews. Especially useful if you
  want to start fresh with a new review - don't forget to comment
  `@sourcery-ai review` to trigger a new review!
- **Generate a plan of action for an issue:** Comment `@sourcery-ai plan` on
  an issue to generate a plan of action for it.

#### Customizing Your Experience

Access your [dashboard](https://app.sourcery.ai) to:
- Enable or disable review features such as the Sourcery-generated pull request
  summary, the reviewer's guide, and others.
- Change the review language.
- Add, remove or edit custom review instructions.
- Adjust other review settings.

#### Getting Help

- [Contact our support team](mailto:support@sourcery.ai) for questions or feedback.
- Visit our [documentation](https://docs.sourcery.ai) for detailed guides and information.
- Keep in touch with the Sourcery team by following us on [X/Twitter](https://x.com/SourceryAI), [LinkedIn](https://www.linkedin.com/company/sourcery-ai/) or [GitHub](https://github.com/sourcery-ai).

</details>

<!-- Generated by sourcery-ai[bot]: end review_guide -->
author_association: NONE
user: login: vercel[bot]
created_at: 2025-04-21T05:03:48Z
body: [vc]: #P5AwjcSt7b9IZdGdcr3PY2jRG8lzr0gwkpM+Ui6d19I=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJhcHBraXQtZGVtbyIsInJvb3REaXJlY3RvcnkiOiJhcHBzL2RlbW8iLCJsaXZlRmVlZGJhY2siOnsicmVzb2x2ZWQiOjAsInVucmVzb2x2ZWQiOjAsInRvdGFsIjowLCJsaW5rIjoiYXBwa2l0LWRlbW8tZ2l0LXJldmVydC00MjQ4LXRvbWFzLWFwLTFkZWUwZS1kYXJnb243ODlzLXByb2plY3RzLnZlcmNlbC5hcHAifSwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL2Rhcmdvbjc4OXMtcHJvamVjdHMvYXBwa2l0LWRlbW8vOHF4OUw5cHR2VnZDZHh1Z3JoV3lYanRCa2tzbSIsInByZXZpZXdVcmwiOiJhcHBraXQtZGVtby1naXQtcmV2ZXJ0LTQyNDgtdG9tYXMtYXAtMWRlZTBlLWRhcmdvbjc4OXMtcHJvamVjdHMudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCJ9LHsibmFtZSI6ImFwcGtpdC13YWxsZXRraXQiLCJyb290RGlyZWN0b3J5IjoiYXBwcy9kZW1vIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImFwcGtpdC13YWxsZXRraXQtZ2l0LXJldmVydC00MjQ4LXRvbS1mYjRlMWItZGFyZ29uNzg5cy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9kYXJnb243ODlzLXByb2plY3RzL2FwcGtpdC13YWxsZXRraXQvSE54VFN6Mnh2N2JMWHZoUmhjcnd4Rzhld2FWViIsInByZXZpZXdVcmwiOiJhcHBraXQtd2FsbGV0a2l0LWdpdC1yZXZlcnQtNDI0OC10b20tZmI0ZTFiLWRhcmdvbjc4OXMtcHJvamVjdHMudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCJ9LHsibmFtZSI6ImFwcGtpdC1kZW1vLWRmMzIiLCJyb290RGlyZWN0b3J5IjoiYXBwcy9kZW1vIiwibGl2ZUZlZWRiYWNrIjp7InJlc29sdmVkIjowLCJ1bnJlc29sdmVkIjowLCJ0b3RhbCI6MCwibGluayI6ImFwcGtpdC1kZW1vLWRmMzItZ2l0LXJldmVydC00MjQ4LXRvbS02MzAxYWYtZGFyZ29uNzg5cy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9kYXJnb243ODlzLXByb2plY3RzL2FwcGtpdC1kZW1vLWRmMzIvNVFBS0xydFFYQnVWZHVOOU1Rd2g5Mjl1VzNrYiIsInByZXZpZXdVcmwiOiJhcHBraXQtZGVtby1kZjMyLWdpdC1yZXZlcnQtNDI0OC10b20tNjMwMWFmLWRhcmdvbjc4OXMtcHJvamVjdHMudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **appkit-demo** | ✅ Ready ([Inspect](https://vercel.com/dargon789s-projects/appkit-demo/8qx9L9ptvVvCdxugrhWyXjtBkksm)) | [Visit Preview](https://appkit-demo-git-revert-4248-tomas-ap-1dee0e-dargon789s-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/appkit-demo-git-revert-4248-tomas-ap-1dee0e-dargon789s-projects.vercel.app?via=pr-comment-feedback-link) | Apr 21, 2025 5:03am |
| **appkit-demo-df32** | ✅ Ready ([Inspect](https://vercel.com/dargon789s-projects/appkit-demo-df32/5QAKLrtQXBuVduN9MQwh929uW3kb)) | [Visit Preview](https://appkit-demo-df32-git-revert-4248-tom-6301af-dargon789s-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/appkit-demo-df32-git-revert-4248-tom-6301af-dargon789s-projects.vercel.app?via=pr-comment-feedback-link) | Apr 21, 2025 5:03am |
| **appkit-walletkit** | ✅ Ready ([Inspect](https://vercel.com/dargon789s-projects/appkit-walletkit/HNxTSz2xv7bLXvhRhcrwxG8ewaVV)) | [Visit Preview](https://appkit-walletkit-git-revert-4248-tom-fb4e1b-dargon789s-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/appkit-walletkit-git-revert-4248-tom-fb4e1b-dargon789s-projects.vercel.app?via=pr-comment-feedback-link) | Apr 21, 2025 5:03am |




author_association: NONE
user: login: snyk-io[bot]
created_at: 2025-04-21T05:03:54Z
body: ![](https://res.cloudinary.com/snyk/image/upload/r-d/scm-platform/snyk-pull-requests/pr-banner-default.svg)

### :tada: **Snyk checks have passed. No issues have been found so far.**

:white_check_mark: **security/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/dargon789/pr-checks/daff8524-9c13-4187-bc03-6bc75e905277?refs=2f33574fd43ed1988b2118285378c82f03923c88&source=prChecksComment)



author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-21T05:10:56Z
body: <h2>Coverage Report</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">74.7%</td> <td align="right">25336 / 33916</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">74.7%</td> <td align="right">25336 / 33916</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">66.22%</td> <td align="right">2141 / 3233</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">83.12%</td> <td align="right">4896 / 5890</td> </tr> </tbody> </table><details><summary>File Coverage</summary><table> <thead> <tr> <th align="left">File</th> <th align="right">Stmts</th> <th align="right">Branches</th> <th align="right">Functions</th> <th align="right">Lines</th> <th align="left">Uncovered Lines</th> </tr> </thead> <tbody> <tr> <td align="left" colspan="6"><b>Changed Files</b></td> </tr> <tr> <td align="left"><a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts">packages/controllers/src/controllers/SendController.ts</a></td> <td align="right">51.43%</td> <td align="right">69.81%</td> <td align="right">58.53%</td> <td align="right">51.43%</td> <td align="left"><a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L69" class="text-red">69</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L119-L121" class="text-red">119-121</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L123" class="text-red">123</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L148-L169" class="text-red">148-169</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L212-L226" class="text-red">212-226</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L234-L235" class="text-red">234-235</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L247-L248" class="text-red">247-248</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L260-L316" class="text-red">260-316</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L335" class="text-red">335</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L337-L352" class="text-red">337-352</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L354-L371" class="text-red">354-371</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L375-L399" class="text-red">375-399</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/controllers/src/controllers/SendController.ts#L139-L368" class="text-red">139-368</a></td> </tr> <tr> <td align="left"><a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts">packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts</a></td> <td align="right">89.02%</td> <td align="right">71.42%</td> <td align="right">85.71%</td> <td align="right">89.02%</td> <td align="left"><a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts#L42-L47" class="text-red">42-47</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts#L128" class="text-red">128</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts#L139" class="text-red">139</a>, <a href="https://github.com/Dargon789/appkit/blob/a6dcb3d1e4de9c4d5c53f57b99d65240de887935/packages/scaffold-ui/src/views/w3m-wallet-send-preview-view/index.ts#L142" class="text-red">142</a></td> </tr> </tbody> </table></details>
<em>Generated in workflow <a href=https://github.com/Dargon789/appkit/actions/runs/14567646441>#135</a> for commit <a href="https://github.com/Dargon789/appkit/commit/a6dcb3d1e4de9c4d5c53f57b99d65240de887935">a6dcb3d</a> by the <a href="https://github.com/davelosert/vitest-coverage-report-action">Vitest Coverage Report Action</a></em>

<!-- vitest-coverage-report-marker-root -->
author_association: NONE