Skip to content

Commit dd5d357

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 dd5d357

32 files changed

Lines changed: 577 additions & 372 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/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/config.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,29 @@ Config::set_log_path(const std::string& path)
119119
return *this;
120120
}
121121

122+
void
123+
Config::refresh_access_token(int64_t expired_at,
124+
AsyncCallback<NoContext, std::string> callback)
125+
{
126+
lb_config_refresh_access_token(
127+
config_,
128+
expired_at,
129+
[](auto res) {
130+
auto callback_ptr =
131+
callback::get_async_callback<NoContext, std::string>(res->userdata);
132+
Status status(res->error);
133+
134+
if (status) {
135+
std::string access_token = (const char*)res->data;
136+
137+
(*callback_ptr)(AsyncResult<NoContext, std::string>(
138+
NoContext{}, std::move(status), &access_token));
139+
} else {
140+
(*callback_ptr)(
141+
AsyncResult<NoContext, std::string>(NoContext{}, std::move(status), nullptr));
142+
}
143+
},
144+
new AsyncCallback<NoContext, std::string>(callback));
145+
}
146+
122147
} // namespace longbridge

cpp/src/http_client.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ HttpClient::request(
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
std::vector<lb_http_header_t> c_headers;
7575
if (headers) {
@@ -88,20 +88,20 @@ HttpClient::request(
8888
body ? body->c_str() : nullptr,
8989
[](auto res) {
9090
auto callback_ptr =
91-
callback::get_async_callback<void*, HttpResult>(res->userdata);
91+
callback::get_async_callback<NoContext, HttpResult>(res->userdata);
9292
Status status(res->error);
9393

9494
if (status) {
9595
const lb_http_result_t* result = (const lb_http_result_t*)res->data;
9696
HttpResult http_res(lb_http_result_response_body(result));
97-
(*callback_ptr)(AsyncResult<void*, HttpResult>(
98-
nullptr, std::move(status), &http_res));
97+
(*callback_ptr)(AsyncResult<NoContext, HttpResult>(
98+
NoContext{}, std::move(status), &http_res));
9999
} else {
100100
(*callback_ptr)(
101-
AsyncResult<void*, HttpResult>(nullptr, std::move(status), nullptr));
101+
AsyncResult<NoContext, HttpResult>(NoContext{}, std::move(status), nullptr));
102102
}
103103
},
104-
new AsyncCallback<void*, HttpResult>(callback));
104+
new AsyncCallback<NoContext, HttpResult>(callback));
105105
}
106106

107107
} // namespace longbridge

0 commit comments

Comments
 (0)