Skip to content

Commit c81d5d7

Browse files
hogan-yuanclaude
andcommitted
fix(alert): resolve merge conflicts with main
- blocking/alert.rs: keep update() replacing enable/disable - python/alert/types.rs: add manual FromPyObject impl for AlertItem (needed since skip_from_py_object prevents auto-derivation) and adopt skip_from_py_object for AlertSymbolGroup/AlertList from main - c/csrc/include/longbridge.h: accept auto-merged version Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
2 parents 2a2b5cb + b7cb9a5 commit c81d5d7

34 files changed

Lines changed: 595 additions & 392 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
# [Unreleased]
7+
# [4.0.6]
88

99
## Added
1010

@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
- **All languages:** `QuoteContext` gains `short_positions`, `option_volume`, `option_volume_daily`, and `update_pinned`.
2020
- **All languages:** `ContentContext` gains `topic_detail`, `list_topic_replies`, and `create_topic_reply`.
2121
- **Rust:** `Config::header(key, value)` builder method for injecting custom HTTP/WebSocket headers.
22+
- **All languages (Rust, Python, Node.js, Java, C, C++):** Restore `Config::refresh_access_token` (and `refresh_access_token_blocking` in Rust). Refreshes the access token via the Longbridge token-refresh API. Only available with **Legacy API Key** authentication (`Config::from_apikey`); not supported in OAuth 2.0 mode.
2223

2324
## Changed
2425

Cargo.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ resolver = "3"
33
members = ["rust", "python", "nodejs", "java", "c"]
44

55
[workspace.package]
6-
version = "4.0.5"
6+
version = "4.0.6"
77
edition = "2024"
88

99
[profile.release]
1010
lto = true
1111

1212
[workspace.dependencies]
13-
longbridge-geo = { path = "rust/crates/geo", version = "4.0.5" }
14-
longbridge-wscli = { path = "rust/crates/wsclient", version = "4.0.5" }
15-
longbridge-httpcli = { path = "rust/crates/httpclient", version = "4.0.5" }
16-
longbridge-proto = { path = "rust/crates/proto", version = "4.0.5" }
17-
longbridge-candlesticks = { path = "rust/crates/candlesticks", version = "4.0.5" }
18-
longbridge-oauth = { path = "rust/crates/oauth", version = "4.0.5" }
19-
longbridge = { path = "rust", version = "4.0.5" }
13+
longbridge-geo = { path = "rust/crates/geo", version = "4.0.6" }
14+
longbridge-wscli = { path = "rust/crates/wsclient", version = "4.0.6" }
15+
longbridge-httpcli = { path = "rust/crates/httpclient", version = "4.0.6" }
16+
longbridge-proto = { path = "rust/crates/proto", version = "4.0.6" }
17+
longbridge-candlesticks = { path = "rust/crates/candlesticks", version = "4.0.6" }
18+
longbridge-oauth = { path = "rust/crates/oauth", version = "4.0.6" }
19+
longbridge = { path = "rust", version = "4.0.6" }
2020

2121
tokio = "1.47.1"
2222
tokio-tungstenite = "0.27.0"

c/csrc/include/longbridge.h

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7877,31 +7877,19 @@ void lb_alert_context_add(const struct lb_alert_context_t *ctx,
78777877
void *userdata);
78787878

78797879
/**
7880-
* Enable a price alert.
7880+
* Update (enable or disable) a price alert.
78817881
*
78827882
* `item` must point to a valid [`CAlertItem`] obtained from
7883-
* [`lb_alert_context_list`]. All fields are read before the function
7883+
* [`lb_alert_context_list`]. Set `enabled` to `true` to re-enable or
7884+
* `false` to disable. All fields of `item` are read before the function
78847885
* returns, so the pointer only needs to be valid for the duration of
78857886
* the call.
78867887
*/
7887-
void lb_alert_context_enable(const struct lb_alert_context_t *ctx,
7888+
void lb_alert_context_update(const struct lb_alert_context_t *ctx,
78887889
const struct lb_alert_item_t *item,
78897890
lb_async_callback_t callback,
78907891
void *userdata);
78917892

7892-
/**
7893-
* Disable a price alert.
7894-
*
7895-
* `item` must point to a valid [`CAlertItem`] obtained from
7896-
* [`lb_alert_context_list`]. All fields are read before the function
7897-
* returns, so the pointer only needs to be valid for the duration of
7898-
* the call.
7899-
*/
7900-
void lb_alert_context_disable(const struct lb_alert_context_t *ctx,
7901-
const struct lb_alert_item_t *item,
7902-
lb_async_callback_t callback,
7903-
void *userdata);
7904-
79057893
/**
79067894
* Delete price alerts. alert_ids: array of alert ID strings, num_ids: count.
79077895
*/
@@ -8087,6 +8075,26 @@ void lb_config_disable_print_quote_packages(struct lb_config_t *config);
80878075
*/
80888076
void lb_config_set_log_path(struct lb_config_t *config, const char *log_path);
80898077

8078+
/**
8079+
* Gets a new `access_token`
8080+
*
8081+
* This function is only available when using **Legacy API Key**
8082+
* authentication (i.e. `lb_config_from_apikey`). It is not supported for
8083+
* OAuth 2.0 mode.
8084+
*
8085+
* @param config Config object
8086+
* @param expired_at Unix timestamp for token expiry. Pass `0` to use the
8087+
* default (90 days from now).
8088+
* @param callback Callback function; on success `res->data` is a
8089+
* `const char*` access token (valid only within the
8090+
* callback body).
8091+
* @param userdata Opaque pointer forwarded to the callback
8092+
*/
8093+
void lb_config_refresh_access_token(struct lb_config_t *config,
8094+
int64_t expired_at,
8095+
lb_async_callback_t callback,
8096+
void *userdata);
8097+
80908098
/**
80918099
* Free the config object
80928100
*/

c/src/config.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
use std::{ffi::CStr, os::raw::c_char, ptr};
1+
use std::{
2+
ffi::{CStr, c_void},
3+
os::raw::c_char,
4+
ptr,
5+
};
26

37
use longbridge::Config;
8+
use time::OffsetDateTime;
49

510
use crate::{
11+
async_call::{CAsyncCallback, execute_async},
612
error::{CError, set_error},
713
oauth::COAuth,
8-
types::{CLanguage, CPushCandlestickMode},
14+
types::{CLanguage, CPushCandlestickMode, CString},
915
};
1016

1117
/// Configuration options for Longbridge SDK
@@ -175,6 +181,40 @@ pub unsafe extern "C" fn lb_config_set_log_path(config: *mut CConfig, log_path:
175181
(*config).0.set_log_path(path);
176182
}
177183

184+
/// Gets a new `access_token`
185+
///
186+
/// This function is only available when using **Legacy API Key**
187+
/// authentication (i.e. `lb_config_from_apikey`). It is not supported for
188+
/// OAuth 2.0 mode.
189+
///
190+
/// @param config Config object
191+
/// @param expired_at Unix timestamp for token expiry. Pass `0` to use the
192+
/// default (90 days from now).
193+
/// @param callback Callback function; on success `res->data` is a
194+
/// `const char*` access token (valid only within the
195+
/// callback body).
196+
/// @param userdata Opaque pointer forwarded to the callback
197+
#[unsafe(no_mangle)]
198+
pub unsafe extern "C" fn lb_config_refresh_access_token(
199+
config: *mut CConfig,
200+
expired_at: i64,
201+
callback: CAsyncCallback,
202+
userdata: *mut c_void,
203+
) {
204+
let config = &mut (*config).0;
205+
execute_async::<c_void, _, _>(callback, std::ptr::null(), userdata, async move {
206+
let token: CString = config
207+
.refresh_access_token(if expired_at == 0 {
208+
None
209+
} else {
210+
Some(OffsetDateTime::from_unix_timestamp(expired_at).unwrap())
211+
})
212+
.await?
213+
.into();
214+
Ok(token)
215+
});
216+
}
217+
178218
/// Free the config object
179219
#[unsafe(no_mangle)]
180220
pub unsafe extern "C" fn lb_config_free(config: *mut CConfig) {

cpp/include/alert_context.hpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,10 @@ class AlertContext {
4545
void add(const std::string& symbol, AlertCondition condition,
4646
const std::string& trigger_value, AlertFrequency frequency,
4747
AsyncCallback<AlertContext, void> callback) const;
48-
/// Enable a price alert by alert_id.
49-
void enable(const std::string& alert_id,
48+
/// Update (enable or disable) a price alert.
49+
/// Set item.enabled before calling to choose the new state.
50+
void update(const AlertItem& item,
5051
AsyncCallback<AlertContext, void> callback) const;
51-
/// Disable a price alert by alert_id.
52-
void disable(const std::string& alert_id,
53-
AsyncCallback<AlertContext, void> callback) const;
5452
};
5553

5654
} // namespace alert

cpp/include/async_result.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,9 @@ struct AsyncResult
4747
template<typename Ctx, typename T>
4848
using AsyncCallback = std::function<void(AsyncResult<Ctx, T>)>;
4949

50+
/// Placeholder context type for async operations that have no meaningful
51+
/// context (analogous to `()` in Rust).
52+
struct NoContext
53+
{};
54+
5055
} // namespace longbridge

cpp/include/config.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ class Config
8989

9090
/// Set the log file path
9191
Config& set_log_path(const std::string& path);
92+
93+
/// Gets a new `access_token`
94+
///
95+
/// This method is only available when using **Legacy API Key**
96+
/// authentication (i.e. `Config::from_apikey`). It is not supported for
97+
/// OAuth 2.0 mode.
98+
///
99+
/// @param expired_at Unix timestamp for token expiry. Pass `0` to use the
100+
/// default (90 days from now).
101+
/// @param callback Callback invoked with the new access token string.
102+
void refresh_access_token(int64_t expired_at,
103+
AsyncCallback<NoContext, std::string> callback);
92104
};
93105

94106
} // namespace longbridge

cpp/include/http_client.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class HttpClient
6969
const std::string& path,
7070
const std::optional<std::map<std::string, std::string>>& headers,
7171
const std::optional<std::string>& body,
72-
AsyncCallback<void*, HttpResult> callback);
72+
AsyncCallback<NoContext, HttpResult> callback);
7373
};
7474

7575
}

cpp/include/oauth.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class OAuthBuilder
5454
/// @param open_url Called with the authorization URL during the auth flow
5555
/// @param callback Invoked on completion; result data is `OAuth*`
5656
void build(std::function<void(const std::string&)> open_url,
57-
AsyncCallback<void*, OAuth> callback);
57+
AsyncCallback<NoContext, OAuth> callback);
5858
};
5959

6060
} // namespace longbridge

cpp/src/alert_context.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ void lb_alert_context_retain(const lb_alert_context_t*);
88
void lb_alert_context_release(const lb_alert_context_t*);
99
void lb_alert_context_list(const lb_alert_context_t*, lb_async_callback_t, void*);
1010
void lb_alert_context_add(const lb_alert_context_t*, const char*, lb_alert_condition_t, const char*, lb_alert_frequency_t, lb_async_callback_t, void*);
11-
void lb_alert_context_enable(const lb_alert_context_t*, const char*, lb_async_callback_t, void*);
12-
void lb_alert_context_disable(const lb_alert_context_t*, const char*, lb_async_callback_t, void*);
11+
void lb_alert_context_update(const lb_alert_context_t*, const lb_alert_item_t*, lb_async_callback_t, void*);
1312
}
1413

1514
namespace longbridge {
@@ -50,20 +49,21 @@ void AlertContext::add(const std::string& symbol, AlertCondition condition,
5049
}, new AsyncCallback<AlertContext, void>(callback));
5150
}
5251

53-
void AlertContext::enable(const std::string& alert_id,
52+
void AlertContext::update(const AlertItem& item,
5453
AsyncCallback<AlertContext, void> callback) const {
55-
lb_alert_context_enable(ctx_, alert_id.c_str(),
56-
[](auto res) {
57-
auto cb = callback::get_async_callback<AlertContext, void>(res->userdata);
58-
AlertContext fctx((const lb_alert_context_t*)res->ctx);
59-
Status status(res->error);
60-
(*cb)(AsyncResult<AlertContext, void>(fctx, std::move(status), nullptr));
61-
}, new AsyncCallback<AlertContext, void>(callback));
62-
}
63-
64-
void AlertContext::disable(const std::string& alert_id,
65-
AsyncCallback<AlertContext, void> callback) const {
66-
lb_alert_context_disable(ctx_, alert_id.c_str(),
54+
// Build a lb_alert_item_t from the C++ AlertItem to pass to the C layer.
55+
std::vector<int32_t> state_copy = item.state;
56+
lb_alert_item_t c_item{};
57+
c_item.id = item.id.c_str();
58+
c_item.indicator_id = item.indicator_id.c_str();
59+
c_item.enabled = item.enabled;
60+
c_item.frequency = item.frequency;
61+
c_item.scope = item.scope;
62+
c_item.text = item.text.c_str();
63+
c_item.state = state_copy.data();
64+
c_item.num_state = state_copy.size();
65+
c_item.value_map = item.value_map.c_str();
66+
lb_alert_context_update(ctx_, &c_item,
6767
[](auto res) {
6868
auto cb = callback::get_async_callback<AlertContext, void>(res->userdata);
6969
AlertContext fctx((const lb_alert_context_t*)res->ctx);

0 commit comments

Comments
 (0)